DuyTa's picture
Upload folder using huggingface_hub
bc20498 verified
import { addEventListener, addMeltEventListener, createElHelpers, disabledAttr, effect, executeCallbacks, getDirectionalKeys, getElemDirection, isHTMLElement, kbd, makeElement, omit, overridable, toWritableStores, } from '../../internal/helpers/index.js';
import { safeOnMount } from '../../internal/helpers/lifecycle.js';
import { derived, writable } from 'svelte/store';
import { createHiddenInput } from '../hidden-input/create.js';
const defaults = {
orientation: 'vertical',
loop: true,
disabled: false,
required: false,
defaultValue: undefined,
};
const prefix = 'radio-group';
const { name, selector } = createElHelpers(prefix);
export function createRadioGroup(props) {
const withDefaults = { ...defaults, ...props };
// options
const options = toWritableStores(omit(withDefaults, 'value'));
const { disabled, required, loop, orientation } = options;
const valueWritable = withDefaults.value ?? writable(withDefaults.defaultValue);
const value = overridable(valueWritable, withDefaults?.onValueChange);
/** Lifecycle & Effects */
const focusedHistory = {
prev: null,
curr: null,
};
safeOnMount(() => {
return addEventListener(document, 'focus', (e) => {
const focusedItem = e.target;
if (!isHTMLElement(focusedItem))
return;
focusedHistory.prev = focusedHistory.curr;
focusedHistory.curr = focusedItem;
});
});
let hasActiveTabIndex = false;
effect(value, ($value) => {
if ($value === undefined) {
hasActiveTabIndex = false;
}
else {
hasActiveTabIndex = true;
}
});
/* Helpers */
const selectItem = (item) => {
const disabled = item.dataset.disabled === 'true';
const itemValue = item.dataset.value;
if (disabled || itemValue === undefined)
return;
value.set(itemValue);
};
/** Elements */
const root = makeElement(name(), {
stores: [required, orientation],
returned: ([$required, $orientation]) => {
return {
role: 'radiogroup',
'aria-required': $required,
'data-orientation': $orientation,
};
},
});
const item = makeElement(name('item'), {
stores: [value, orientation, disabled],
returned: ([$value, $orientation, $disabled]) => {
return (props) => {
const itemValue = typeof props === 'string' ? props : props.value;
const argDisabled = typeof props === 'string' ? false : !!props.disabled;
const disabled = $disabled || argDisabled;
const checked = $value === itemValue;
const tabindex = !hasActiveTabIndex ? 0 : checked ? 0 : -1;
hasActiveTabIndex = true;
return {
disabled,
'data-value': itemValue,
'data-orientation': $orientation,
'data-disabled': disabledAttr(disabled),
'data-state': checked ? 'checked' : 'unchecked',
'aria-checked': checked,
type: 'button',
role: 'radio',
tabindex,
};
};
},
action: (node) => {
const unsub = executeCallbacks(addMeltEventListener(node, 'click', () => {
selectItem(node);
}), addMeltEventListener(node, 'keydown', (e) => {
const el = e.currentTarget;
if (!isHTMLElement(el))
return;
const root = el.closest(selector());
if (!isHTMLElement(root))
return;
const items = Array.from(root.querySelectorAll(selector('item'))).filter((el) => isHTMLElement(el) && !el.hasAttribute('data-disabled'));
const currentIndex = items.indexOf(el);
const dir = getElemDirection(root);
const { nextKey, prevKey } = getDirectionalKeys(dir, orientation.get());
const $loop = loop.get();
let itemToFocus = null;
if (e.key === nextKey) {
e.preventDefault();
const nextIndex = currentIndex + 1;
if (nextIndex >= items.length && $loop) {
itemToFocus = items[0];
}
else {
itemToFocus = items[nextIndex];
}
}
else if (e.key === prevKey) {
e.preventDefault();
const prevIndex = currentIndex - 1;
if (prevIndex < 0 && $loop) {
itemToFocus = items[items.length - 1];
}
else {
itemToFocus = items[prevIndex];
}
}
else if (e.key === kbd.HOME) {
e.preventDefault();
itemToFocus = items[0];
}
else if (e.key === kbd.END) {
e.preventDefault();
itemToFocus = items[items.length - 1];
}
if (itemToFocus) {
itemToFocus.focus();
selectItem(itemToFocus);
}
}));
return {
destroy: unsub,
};
},
});
const hiddenInput = createHiddenInput({
value,
disabled,
required,
});
const isChecked = derived(value, ($value) => {
return (itemValue) => {
return $value === itemValue;
};
});
return {
elements: {
root,
item,
hiddenInput,
},
states: {
value,
},
helpers: {
isChecked,
},
options,
};
}