@auronui/vue 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +759 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/composables/useAccordion.js +58 -0
- package/dist/composables/useAccordion.js.map +1 -0
- package/dist/composables/useCalendar.js +47 -0
- package/dist/composables/useCalendar.js.map +1 -0
- package/dist/composables/useCheckboxGroup.js +64 -0
- package/dist/composables/useCheckboxGroup.js.map +1 -0
- package/dist/composables/useColorPicker.js +68 -0
- package/dist/composables/useColorPicker.js.map +1 -0
- package/dist/composables/useDisclosure.js +43 -0
- package/dist/composables/useDisclosure.js.map +1 -0
- package/dist/composables/useListBox.js +61 -0
- package/dist/composables/useListBox.js.map +1 -0
- package/dist/composables/useOTP.js +29 -0
- package/dist/composables/useOTP.js.map +1 -0
- package/dist/composables/usePagination.js +54 -0
- package/dist/composables/usePagination.js.map +1 -0
- package/dist/composables/useRadioGroup.js +38 -0
- package/dist/composables/useRadioGroup.js.map +1 -0
- package/dist/composables/useRangeCalendar.js +51 -0
- package/dist/composables/useRangeCalendar.js.map +1 -0
- package/dist/composables/useSlider.js +46 -0
- package/dist/composables/useSlider.js.map +1 -0
- package/dist/composables/useSplitter.js +39 -0
- package/dist/composables/useSplitter.js.map +1 -0
- package/dist/composables/useStepper.js +58 -0
- package/dist/composables/useStepper.js.map +1 -0
- package/dist/composables/useSwatchPicker.js +31 -0
- package/dist/composables/useSwatchPicker.js.map +1 -0
- package/dist/composables/useTabs.js +34 -0
- package/dist/composables/useTabs.js.map +1 -0
- package/dist/composables/useTree.js +88 -0
- package/dist/composables/useTree.js.map +1 -0
- package/dist/index.d.ts +786 -64
- package/dist/index.js +17 -1
- package/package.json +4 -4
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
//#region src/composables/useAccordion.ts
|
|
3
|
+
/**
|
|
4
|
+
* Manages expanded item state for the Accordion component.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const accordion = useAccordion({ type: 'single', collapsible: true })
|
|
9
|
+
* ```
|
|
10
|
+
* ```html
|
|
11
|
+
* <Accordion :type="'single'" :model-value="accordion.expanded" @update:model-value="accordion.onValueChange">
|
|
12
|
+
* ...
|
|
13
|
+
* </Accordion>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
function useAccordion(options = {}) {
|
|
17
|
+
const type = options.type ?? "single";
|
|
18
|
+
const collapsible = options.collapsible ?? false;
|
|
19
|
+
const expanded = ref(options.defaultExpanded ?? (type === "multiple" ? [] : void 0));
|
|
20
|
+
function isExpanded(key) {
|
|
21
|
+
if (type === "multiple") return expanded.value.includes(key);
|
|
22
|
+
return expanded.value === key;
|
|
23
|
+
}
|
|
24
|
+
function expand(key) {
|
|
25
|
+
if (type === "multiple") {
|
|
26
|
+
const current = expanded.value;
|
|
27
|
+
if (!current.includes(key)) expanded.value = [...current, key];
|
|
28
|
+
} else expanded.value = key;
|
|
29
|
+
}
|
|
30
|
+
function collapse(key) {
|
|
31
|
+
if (type === "multiple") expanded.value = expanded.value.filter((k) => k !== key);
|
|
32
|
+
else if (collapsible && expanded.value === key) expanded.value = void 0;
|
|
33
|
+
}
|
|
34
|
+
function toggle(key) {
|
|
35
|
+
if (isExpanded(key)) collapse(key);
|
|
36
|
+
else expand(key);
|
|
37
|
+
}
|
|
38
|
+
function collapseAll() {
|
|
39
|
+
if (type === "multiple") expanded.value = [];
|
|
40
|
+
else if (collapsible) expanded.value = void 0;
|
|
41
|
+
}
|
|
42
|
+
function onValueChange(value) {
|
|
43
|
+
expanded.value = value;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
expanded,
|
|
47
|
+
isExpanded,
|
|
48
|
+
expand,
|
|
49
|
+
collapse,
|
|
50
|
+
toggle,
|
|
51
|
+
collapseAll,
|
|
52
|
+
onValueChange
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { useAccordion };
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=useAccordion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAccordion.js","names":[],"sources":["../../src/composables/useAccordion.ts"],"sourcesContent":["import { ref, type Ref } from 'vue'\n\nexport type AccordionType = 'single' | 'multiple'\nexport type AccordionValue = string | string[] | undefined\n\nexport interface UseAccordionOptions {\n /** Whether to allow only one item open at a time ('single') or multiple ('multiple'). Defaults to 'single'. */\n type?: AccordionType\n /** Initial expanded item(s). String for single mode, string[] for multiple mode. */\n defaultExpanded?: AccordionValue\n /** In single mode, whether all items can be collapsed. Defaults to false. */\n collapsible?: boolean\n}\n\nexport interface UseAccordionReturn {\n /** Reactive expanded item(s). String in single mode, string[] in multiple mode. */\n expanded: Ref<AccordionValue>\n /** Whether a given item is currently expanded. */\n isExpanded: (key: string) => boolean\n /** Expand a specific item. */\n expand: (key: string) => void\n /** Collapse a specific item. No-op in single non-collapsible mode. */\n collapse: (key: string) => void\n /** Toggle a specific item open or closed. */\n toggle: (key: string) => void\n /** Collapse all items. Only fully effective in multiple or collapsible-single mode. */\n collapseAll: () => void\n /**\n * Pass as `@update:model-value` handler on the Accordion component.\n * Keeps `expanded` in sync when the component changes state internally.\n */\n onValueChange: (value: AccordionValue) => void\n}\n\n/**\n * Manages expanded item state for the Accordion component.\n *\n * @example\n * ```ts\n * const accordion = useAccordion({ type: 'single', collapsible: true })\n * ```\n * ```html\n * <Accordion :type=\"'single'\" :model-value=\"accordion.expanded\" @update:model-value=\"accordion.onValueChange\">\n * ...\n * </Accordion>\n * ```\n */\nexport function useAccordion(options: UseAccordionOptions = {}): UseAccordionReturn {\n const type = options.type ?? 'single'\n const collapsible = options.collapsible ?? false\n\n const expanded = ref<AccordionValue>(\n options.defaultExpanded ?? (type === 'multiple' ? [] : undefined)\n )\n\n function isExpanded(key: string): boolean {\n if (type === 'multiple') return (expanded.value as string[]).includes(key)\n return expanded.value === key\n }\n\n function expand(key: string): void {\n if (type === 'multiple') {\n const current = expanded.value as string[]\n if (!current.includes(key)) expanded.value = [...current, key]\n } else {\n expanded.value = key\n }\n }\n\n function collapse(key: string): void {\n if (type === 'multiple') {\n expanded.value = (expanded.value as string[]).filter(k => k !== key)\n } else if (collapsible && expanded.value === key) {\n expanded.value = undefined\n }\n }\n\n function toggle(key: string): void {\n if (isExpanded(key)) collapse(key)\n else expand(key)\n }\n\n function collapseAll(): void {\n if (type === 'multiple') {\n expanded.value = []\n } else if (collapsible) {\n expanded.value = undefined\n }\n }\n\n function onValueChange(value: AccordionValue): void {\n expanded.value = value\n }\n\n return {\n expanded,\n isExpanded,\n expand,\n collapse,\n toggle,\n collapseAll,\n onValueChange,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AA+CA,SAAgB,aAAa,UAA+B,EAAE,EAAsB;CAClF,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,cAAc,QAAQ,eAAe;CAE3C,MAAM,WAAW,IACf,QAAQ,oBAAoB,SAAS,aAAa,EAAE,GAAG,KAAA,GACxD;CAED,SAAS,WAAW,KAAsB;AACxC,MAAI,SAAS,WAAY,QAAQ,SAAS,MAAmB,SAAS,IAAI;AAC1E,SAAO,SAAS,UAAU;;CAG5B,SAAS,OAAO,KAAmB;AACjC,MAAI,SAAS,YAAY;GACvB,MAAM,UAAU,SAAS;AACzB,OAAI,CAAC,QAAQ,SAAS,IAAI,CAAE,UAAS,QAAQ,CAAC,GAAG,SAAS,IAAI;QAE9D,UAAS,QAAQ;;CAIrB,SAAS,SAAS,KAAmB;AACnC,MAAI,SAAS,WACX,UAAS,QAAS,SAAS,MAAmB,QAAO,MAAK,MAAM,IAAI;WAC3D,eAAe,SAAS,UAAU,IAC3C,UAAS,QAAQ,KAAA;;CAIrB,SAAS,OAAO,KAAmB;AACjC,MAAI,WAAW,IAAI,CAAE,UAAS,IAAI;MAC7B,QAAO,IAAI;;CAGlB,SAAS,cAAoB;AAC3B,MAAI,SAAS,WACX,UAAS,QAAQ,EAAE;WACV,YACT,UAAS,QAAQ,KAAA;;CAIrB,SAAS,cAAc,OAA6B;AAClD,WAAS,QAAQ;;AAGnB,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { computed, shallowRef } from "vue";
|
|
2
|
+
//#region src/composables/useCalendar.ts
|
|
3
|
+
/**
|
|
4
|
+
* Manages selected date state for the Calendar component.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const calendar = useCalendar()
|
|
9
|
+
* ```
|
|
10
|
+
* ```html
|
|
11
|
+
* <Calendar v-model="calendar.value" />
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
function useCalendar(options = {}) {
|
|
15
|
+
const value = shallowRef(options.defaultValue);
|
|
16
|
+
const hasValue = computed(() => value.value !== void 0);
|
|
17
|
+
function setValue(date) {
|
|
18
|
+
value.value = date;
|
|
19
|
+
}
|
|
20
|
+
function clear() {
|
|
21
|
+
value.value = void 0;
|
|
22
|
+
}
|
|
23
|
+
function isDisabled(date) {
|
|
24
|
+
if (options.minValue && date.compare(options.minValue) < 0) return true;
|
|
25
|
+
if (options.maxValue && date.compare(options.maxValue) > 0) return true;
|
|
26
|
+
return options.isDateDisabled?.(date) ?? false;
|
|
27
|
+
}
|
|
28
|
+
function isUnavailable(date) {
|
|
29
|
+
return options.isDateUnavailable?.(date) ?? false;
|
|
30
|
+
}
|
|
31
|
+
function onValueChange(date) {
|
|
32
|
+
value.value = date;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
value,
|
|
36
|
+
hasValue,
|
|
37
|
+
setValue,
|
|
38
|
+
clear,
|
|
39
|
+
isDisabled,
|
|
40
|
+
isUnavailable,
|
|
41
|
+
onValueChange
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { useCalendar };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=useCalendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCalendar.js","names":[],"sources":["../../src/composables/useCalendar.ts"],"sourcesContent":["import { shallowRef, computed, type Ref, type ComputedRef } from 'vue'\nimport type { DateValue } from '@internationalized/date'\n\nexport interface UseCalendarOptions {\n /** Initial selected date for uncontrolled usage. */\n defaultValue?: DateValue\n /** Minimum selectable date. */\n minValue?: DateValue\n /** Maximum selectable date. */\n maxValue?: DateValue\n /** Returns true for dates that should be disabled (not selectable). */\n isDateDisabled?: (date: DateValue) => boolean\n /** Returns true for dates that are unavailable (selectable but marked unavailable). */\n isDateUnavailable?: (date: DateValue) => boolean\n}\n\nexport interface UseCalendarReturn {\n /** Reactive selected date value. */\n value: Ref<DateValue | undefined>\n /** Whether a date is currently selected. */\n hasValue: ComputedRef<boolean>\n /** Set the selected date. */\n setValue: (date: DateValue) => void\n /** Clear the selected date. */\n clear: () => void\n /** Returns true if the given date is disabled per the `isDateDisabled` option. */\n isDisabled: (date: DateValue) => boolean\n /** Returns true if the given date is unavailable per the `isDateUnavailable` option. */\n isUnavailable: (date: DateValue) => boolean\n /**\n * Pass as `v-model` on the Calendar component.\n * Keeps `value` in sync when the component changes selection internally.\n */\n onValueChange: (date: DateValue | undefined) => void\n}\n\n/**\n * Manages selected date state for the Calendar component.\n *\n * @example\n * ```ts\n * const calendar = useCalendar()\n * ```\n * ```html\n * <Calendar v-model=\"calendar.value\" />\n * ```\n */\nexport function useCalendar(options: UseCalendarOptions = {}): UseCalendarReturn {\n const value = shallowRef<DateValue | undefined>(options.defaultValue)\n\n const hasValue = computed(() => value.value !== undefined)\n\n function setValue(date: DateValue): void {\n value.value = date\n }\n\n function clear(): void {\n value.value = undefined\n }\n\n function isDisabled(date: DateValue): boolean {\n if (options.minValue && date.compare(options.minValue) < 0) return true\n if (options.maxValue && date.compare(options.maxValue) > 0) return true\n return options.isDateDisabled?.(date) ?? false\n }\n\n function isUnavailable(date: DateValue): boolean {\n return options.isDateUnavailable?.(date) ?? false\n }\n\n function onValueChange(date: DateValue | undefined): void {\n value.value = date\n }\n\n return {\n value,\n hasValue,\n setValue,\n clear,\n isDisabled,\n isUnavailable,\n onValueChange,\n }\n}\n"],"mappings":";;;;;;;;;;;;;AA+CA,SAAgB,YAAY,UAA8B,EAAE,EAAqB;CAC/E,MAAM,QAAQ,WAAkC,QAAQ,aAAa;CAErE,MAAM,WAAW,eAAe,MAAM,UAAU,KAAA,EAAU;CAE1D,SAAS,SAAS,MAAuB;AACvC,QAAM,QAAQ;;CAGhB,SAAS,QAAc;AACrB,QAAM,QAAQ,KAAA;;CAGhB,SAAS,WAAW,MAA0B;AAC5C,MAAI,QAAQ,YAAY,KAAK,QAAQ,QAAQ,SAAS,GAAG,EAAG,QAAO;AACnE,MAAI,QAAQ,YAAY,KAAK,QAAQ,QAAQ,SAAS,GAAG,EAAG,QAAO;AACnE,SAAO,QAAQ,iBAAiB,KAAK,IAAI;;CAG3C,SAAS,cAAc,MAA0B;AAC/C,SAAO,QAAQ,oBAAoB,KAAK,IAAI;;CAG9C,SAAS,cAAc,MAAmC;AACxD,QAAM,QAAQ;;AAGhB,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { computed, ref } from "vue";
|
|
2
|
+
//#region src/composables/useCheckboxGroup.ts
|
|
3
|
+
/**
|
|
4
|
+
* Manages checked state for a CheckboxGroup.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const group = useCheckboxGroup({
|
|
9
|
+
* options: ['apple', 'banana', 'cherry'],
|
|
10
|
+
* defaultValues: ['apple'],
|
|
11
|
+
* })
|
|
12
|
+
* ```
|
|
13
|
+
* ```html
|
|
14
|
+
* <CheckboxGroup :model-value="group.values" @update:model-value="group.onValueChange">
|
|
15
|
+
* <Checkbox value="apple">Apple</Checkbox>
|
|
16
|
+
* <Checkbox value="banana">Banana</Checkbox>
|
|
17
|
+
* <Checkbox value="cherry">Cherry</Checkbox>
|
|
18
|
+
* </CheckboxGroup>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
function useCheckboxGroup(options = {}) {
|
|
22
|
+
const values = ref(options.defaultValues ? [...options.defaultValues] : []);
|
|
23
|
+
function isChecked(value) {
|
|
24
|
+
return values.value.includes(value);
|
|
25
|
+
}
|
|
26
|
+
function toggle(value) {
|
|
27
|
+
if (isChecked(value)) values.value = values.value.filter((v) => v !== value);
|
|
28
|
+
else values.value = [...values.value, value];
|
|
29
|
+
}
|
|
30
|
+
function checkAll(keys) {
|
|
31
|
+
values.value = [...new Set([...values.value, ...keys])];
|
|
32
|
+
}
|
|
33
|
+
function uncheckAll() {
|
|
34
|
+
values.value = [];
|
|
35
|
+
}
|
|
36
|
+
function setValues(next) {
|
|
37
|
+
values.value = [...next];
|
|
38
|
+
}
|
|
39
|
+
function onValueChange(next) {
|
|
40
|
+
values.value = [...next];
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
values,
|
|
44
|
+
isChecked,
|
|
45
|
+
toggle,
|
|
46
|
+
checkAll,
|
|
47
|
+
uncheckAll,
|
|
48
|
+
setValues,
|
|
49
|
+
isIndeterminate: computed(() => {
|
|
50
|
+
if (!options.options || options.options.length === 0) return false;
|
|
51
|
+
const count = values.value.filter((v) => options.options.includes(v)).length;
|
|
52
|
+
return count > 0 && count < options.options.length;
|
|
53
|
+
}),
|
|
54
|
+
isAllChecked: computed(() => {
|
|
55
|
+
if (!options.options || options.options.length === 0) return false;
|
|
56
|
+
return options.options.every((k) => values.value.includes(k));
|
|
57
|
+
}),
|
|
58
|
+
onValueChange
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { useCheckboxGroup };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=useCheckboxGroup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCheckboxGroup.js","names":[],"sources":["../../src/composables/useCheckboxGroup.ts"],"sourcesContent":["import { ref, computed, type Ref, type ComputedRef } from 'vue'\n\nexport interface UseCheckboxGroupOptions {\n /** Initial checked values. */\n defaultValues?: string[]\n /**\n * Full set of option keys in the group.\n * Required for `isIndeterminate` and `isAllChecked` to be accurate.\n */\n options?: string[]\n}\n\nexport interface UseCheckboxGroupReturn {\n /** Reactive array of currently checked values. */\n values: Ref<string[]>\n /** Whether a given value is currently checked. */\n isChecked: (value: string) => boolean\n /** Toggle a value — checks it if unchecked, unchecks if checked. */\n toggle: (value: string) => void\n /** Check all provided values (merges with existing). */\n checkAll: (keys: string[]) => void\n /** Uncheck all values. */\n uncheckAll: () => void\n /** Set the checked values directly. */\n setValues: (values: string[]) => void\n /**\n * True when some — but not all — options are checked.\n * Requires `options` to be provided in the options object.\n */\n isIndeterminate: ComputedRef<boolean>\n /**\n * True when every option is checked.\n * Requires `options` to be provided in the options object.\n */\n isAllChecked: ComputedRef<boolean>\n /**\n * Pass as `@update:model-value` handler on the CheckboxGroup component.\n * Keeps `values` in sync when the component changes state internally.\n */\n onValueChange: (values: string[]) => void\n}\n\n/**\n * Manages checked state for a CheckboxGroup.\n *\n * @example\n * ```ts\n * const group = useCheckboxGroup({\n * options: ['apple', 'banana', 'cherry'],\n * defaultValues: ['apple'],\n * })\n * ```\n * ```html\n * <CheckboxGroup :model-value=\"group.values\" @update:model-value=\"group.onValueChange\">\n * <Checkbox value=\"apple\">Apple</Checkbox>\n * <Checkbox value=\"banana\">Banana</Checkbox>\n * <Checkbox value=\"cherry\">Cherry</Checkbox>\n * </CheckboxGroup>\n * ```\n */\nexport function useCheckboxGroup(options: UseCheckboxGroupOptions = {}): UseCheckboxGroupReturn {\n const values = ref<string[]>(options.defaultValues ? [...options.defaultValues] : [])\n\n function isChecked(value: string): boolean {\n return values.value.includes(value)\n }\n\n function toggle(value: string): void {\n if (isChecked(value)) {\n values.value = values.value.filter(v => v !== value)\n } else {\n values.value = [...values.value, value]\n }\n }\n\n function checkAll(keys: string[]): void {\n values.value = [...new Set([...values.value, ...keys])]\n }\n\n function uncheckAll(): void {\n values.value = []\n }\n\n function setValues(next: string[]): void {\n values.value = [...next]\n }\n\n function onValueChange(next: string[]): void {\n values.value = [...next]\n }\n\n const isIndeterminate = computed<boolean>(() => {\n if (!options.options || options.options.length === 0) return false\n const count = values.value.filter(v => options.options!.includes(v)).length\n return count > 0 && count < options.options.length\n })\n\n const isAllChecked = computed<boolean>(() => {\n if (!options.options || options.options.length === 0) return false\n return options.options.every(k => values.value.includes(k))\n })\n\n return {\n values,\n isChecked,\n toggle,\n checkAll,\n uncheckAll,\n setValues,\n isIndeterminate,\n isAllChecked,\n onValueChange,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA4DA,SAAgB,iBAAiB,UAAmC,EAAE,EAA0B;CAC9F,MAAM,SAAS,IAAc,QAAQ,gBAAgB,CAAC,GAAG,QAAQ,cAAc,GAAG,EAAE,CAAC;CAErF,SAAS,UAAU,OAAwB;AACzC,SAAO,OAAO,MAAM,SAAS,MAAM;;CAGrC,SAAS,OAAO,OAAqB;AACnC,MAAI,UAAU,MAAM,CAClB,QAAO,QAAQ,OAAO,MAAM,QAAO,MAAK,MAAM,MAAM;MAEpD,QAAO,QAAQ,CAAC,GAAG,OAAO,OAAO,MAAM;;CAI3C,SAAS,SAAS,MAAsB;AACtC,SAAO,QAAQ,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,OAAO,OAAO,GAAG,KAAK,CAAC,CAAC;;CAGzD,SAAS,aAAmB;AAC1B,SAAO,QAAQ,EAAE;;CAGnB,SAAS,UAAU,MAAsB;AACvC,SAAO,QAAQ,CAAC,GAAG,KAAK;;CAG1B,SAAS,cAAc,MAAsB;AAC3C,SAAO,QAAQ,CAAC,GAAG,KAAK;;AAc1B,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA,iBAlBsB,eAAwB;AAC9C,OAAI,CAAC,QAAQ,WAAW,QAAQ,QAAQ,WAAW,EAAG,QAAO;GAC7D,MAAM,QAAQ,OAAO,MAAM,QAAO,MAAK,QAAQ,QAAS,SAAS,EAAE,CAAC,CAAC;AACrE,UAAO,QAAQ,KAAK,QAAQ,QAAQ,QAAQ;IAC5C;EAeA,cAbmB,eAAwB;AAC3C,OAAI,CAAC,QAAQ,WAAW,QAAQ,QAAQ,WAAW,EAAG,QAAO;AAC7D,UAAO,QAAQ,QAAQ,OAAM,MAAK,OAAO,MAAM,SAAS,EAAE,CAAC;IAC3D;EAWA;EACD"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { useColorState } from "./useColorState.js";
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
import { colorToHsb, colorToHsl, colorToRgb, parseColor } from "reka-ui";
|
|
4
|
+
//#region src/composables/useColorPicker.ts
|
|
5
|
+
/**
|
|
6
|
+
* High-level composable for controlling the ColorPicker component.
|
|
7
|
+
*
|
|
8
|
+
* Wraps `useColorState` with computed channel accessors and format conversion helpers.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const picker = useColorPicker({ defaultValue: '#3b82f6' })
|
|
13
|
+
* console.log(picker.hue.value) // 217
|
|
14
|
+
* console.log(picker.saturation.value) // 91
|
|
15
|
+
* console.log(picker.brightness.value) // 96
|
|
16
|
+
* ```
|
|
17
|
+
* ```html
|
|
18
|
+
* <ColorPicker v-model="picker.color" />
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
function useColorPicker(options = {}) {
|
|
22
|
+
const state = useColorState({
|
|
23
|
+
defaultValue: options.defaultValue,
|
|
24
|
+
format: options.format ?? "hex",
|
|
25
|
+
onChange: options.onChange
|
|
26
|
+
});
|
|
27
|
+
function setColor(value) {
|
|
28
|
+
const parsed = typeof value === "string" ? parseColor(value) : value;
|
|
29
|
+
state.color.value = parsed;
|
|
30
|
+
options.onChange?.(state.toString(), parsed);
|
|
31
|
+
}
|
|
32
|
+
const hue = computed(() => state.getChannel("hue"));
|
|
33
|
+
const saturation = computed(() => state.getChannel("saturation"));
|
|
34
|
+
const brightness = computed(() => state.getChannel("brightness"));
|
|
35
|
+
const alpha = computed(() => state.getChannel("alpha"));
|
|
36
|
+
function toHex() {
|
|
37
|
+
return state.toHex();
|
|
38
|
+
}
|
|
39
|
+
function toRgb() {
|
|
40
|
+
return colorToRgb(state.color.value).toString();
|
|
41
|
+
}
|
|
42
|
+
function toHsl() {
|
|
43
|
+
return colorToHsl(state.color.value).toString();
|
|
44
|
+
}
|
|
45
|
+
function toHsb() {
|
|
46
|
+
return colorToHsb(state.color.value).toString();
|
|
47
|
+
}
|
|
48
|
+
function onColorChange(value) {
|
|
49
|
+
setColor(value);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
color: state.color,
|
|
53
|
+
setColor,
|
|
54
|
+
hue,
|
|
55
|
+
saturation,
|
|
56
|
+
brightness,
|
|
57
|
+
alpha,
|
|
58
|
+
toHex,
|
|
59
|
+
toRgb,
|
|
60
|
+
toHsl,
|
|
61
|
+
toHsb,
|
|
62
|
+
onColorChange
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
export { useColorPicker };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=useColorPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useColorPicker.js","names":[],"sources":["../../src/composables/useColorPicker.ts"],"sourcesContent":["import { computed, type Ref, type ComputedRef } from 'vue'\nimport { parseColor, colorToRgb, colorToHsl, colorToHsb, type Color, type ColorFormat } from 'reka-ui'\nimport { useColorState } from './useColorState'\n\nexport type { ColorFormat }\nexport type { Color }\n\nexport interface UseColorPickerOptions {\n /** Initial color value. Accepts hex strings (#ff0000), rgb/hsl/hsb strings, or a Color object. Defaults to black. */\n defaultValue?: string | Color\n /** Output format for string serialization methods. Defaults to 'hex'. */\n format?: ColorFormat\n /** Fires with the serialized color string whenever the color changes. */\n onChange?: (value: string, color: Color) => void\n}\n\nexport interface UseColorPickerReturn {\n /** The raw reactive Color object. */\n color: Ref<Color>\n /** Set the color from a string (hex, rgb, hsl, hsb) or a Color object. */\n setColor: (value: string | Color) => void\n /** Computed hue channel value (0–360). */\n hue: ComputedRef<number>\n /** Computed saturation channel value (0–100). */\n saturation: ComputedRef<number>\n /** Computed brightness channel value (0–100). */\n brightness: ComputedRef<number>\n /** Computed alpha channel value (0–100). */\n alpha: ComputedRef<number>\n /** Serialize the current color to a hex string (e.g. '#ff0000'). */\n toHex: () => string\n /** Serialize the current color to an rgb/rgba string. */\n toRgb: () => string\n /** Serialize the current color to an hsl/hsla string. */\n toHsl: () => string\n /** Serialize the current color to an hsb/hsba string. */\n toHsb: () => string\n /**\n * Pass as `@update:model-value` handler on the ColorPicker component.\n * Keeps `color` in sync when the component changes internally.\n */\n onColorChange: (value: string | Color) => void\n}\n\n/**\n * High-level composable for controlling the ColorPicker component.\n *\n * Wraps `useColorState` with computed channel accessors and format conversion helpers.\n *\n * @example\n * ```ts\n * const picker = useColorPicker({ defaultValue: '#3b82f6' })\n * console.log(picker.hue.value) // 217\n * console.log(picker.saturation.value) // 91\n * console.log(picker.brightness.value) // 96\n * ```\n * ```html\n * <ColorPicker v-model=\"picker.color\" />\n * ```\n */\nexport function useColorPicker(options: UseColorPickerOptions = {}): UseColorPickerReturn {\n const state = useColorState({\n defaultValue: options.defaultValue,\n format: options.format ?? 'hex',\n onChange: options.onChange,\n })\n\n function setColor(value: string | Color): void {\n const parsed = typeof value === 'string' ? parseColor(value) : value\n state.color.value = parsed\n options.onChange?.(state.toString(), parsed)\n }\n\n const hue = computed(() => state.getChannel('hue'))\n const saturation = computed(() => state.getChannel('saturation'))\n const brightness = computed(() => state.getChannel('brightness'))\n const alpha = computed(() => state.getChannel('alpha'))\n\n function toHex(): string {\n return state.toHex()\n }\n\n function toRgb(): string {\n return colorToRgb(state.color.value).toString()\n }\n\n function toHsl(): string {\n return colorToHsl(state.color.value).toString()\n }\n\n function toHsb(): string {\n return colorToHsb(state.color.value).toString()\n }\n\n function onColorChange(value: string | Color): void {\n setColor(value)\n }\n\n return {\n color: state.color,\n setColor,\n hue,\n saturation,\n brightness,\n alpha,\n toHex,\n toRgb,\n toHsl,\n toHsb,\n onColorChange,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA4DA,SAAgB,eAAe,UAAiC,EAAE,EAAwB;CACxF,MAAM,QAAQ,cAAc;EAC1B,cAAc,QAAQ;EACtB,QAAQ,QAAQ,UAAU;EAC1B,UAAU,QAAQ;EACnB,CAAC;CAEF,SAAS,SAAS,OAA6B;EAC7C,MAAM,SAAS,OAAO,UAAU,WAAW,WAAW,MAAM,GAAG;AAC/D,QAAM,MAAM,QAAQ;AACpB,UAAQ,WAAW,MAAM,UAAU,EAAE,OAAO;;CAG9C,MAAM,MAAM,eAAe,MAAM,WAAW,MAAM,CAAC;CACnD,MAAM,aAAa,eAAe,MAAM,WAAW,aAAa,CAAC;CACjE,MAAM,aAAa,eAAe,MAAM,WAAW,aAAa,CAAC;CACjE,MAAM,QAAQ,eAAe,MAAM,WAAW,QAAQ,CAAC;CAEvD,SAAS,QAAgB;AACvB,SAAO,MAAM,OAAO;;CAGtB,SAAS,QAAgB;AACvB,SAAO,WAAW,MAAM,MAAM,MAAM,CAAC,UAAU;;CAGjD,SAAS,QAAgB;AACvB,SAAO,WAAW,MAAM,MAAM,MAAM,CAAC,UAAU;;CAGjD,SAAS,QAAgB;AACvB,SAAO,WAAW,MAAM,MAAM,MAAM,CAAC,UAAU;;CAGjD,SAAS,cAAc,OAA6B;AAClD,WAAS,MAAM;;AAGjB,QAAO;EACL,OAAO,MAAM;EACb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readonly, ref } from "vue";
|
|
2
|
+
//#region src/composables/useDisclosure.ts
|
|
3
|
+
/**
|
|
4
|
+
* Manages programmatic open/close state for overlay components.
|
|
5
|
+
*
|
|
6
|
+
* Wire the returned refs and handlers directly into the component:
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const modal = useDisclosure()
|
|
11
|
+
* await saveData()
|
|
12
|
+
* modal.open()
|
|
13
|
+
* ```
|
|
14
|
+
* ```html
|
|
15
|
+
* <Modal :open="modal.isOpen" @update:open="modal.onOpenChange">...</Modal>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
function useDisclosure(defaultOpen = false) {
|
|
19
|
+
const _isOpen = ref(defaultOpen);
|
|
20
|
+
function open() {
|
|
21
|
+
_isOpen.value = true;
|
|
22
|
+
}
|
|
23
|
+
function close() {
|
|
24
|
+
_isOpen.value = false;
|
|
25
|
+
}
|
|
26
|
+
function toggle() {
|
|
27
|
+
_isOpen.value = !_isOpen.value;
|
|
28
|
+
}
|
|
29
|
+
function onOpenChange(value) {
|
|
30
|
+
_isOpen.value = value;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
isOpen: readonly(_isOpen),
|
|
34
|
+
open,
|
|
35
|
+
close,
|
|
36
|
+
toggle,
|
|
37
|
+
onOpenChange
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { useDisclosure };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=useDisclosure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDisclosure.js","names":[],"sources":["../../src/composables/useDisclosure.ts"],"sourcesContent":["import { ref, readonly } from 'vue'\n\nexport interface UseDisclosureReturn {\n /** Whether the element is currently open. */\n isOpen: Readonly<ReturnType<typeof ref<boolean>>>\n /** Open the element. */\n open: () => void\n /** Close the element. */\n close: () => void\n /** Toggle the element open/closed. */\n toggle: () => void\n /**\n * Pass as `@update:open` handler on the component.\n * Keeps `isOpen` in sync when the component closes itself (e.g. Escape key, backdrop click).\n */\n onOpenChange: (value: boolean) => void\n}\n\n/**\n * Manages programmatic open/close state for overlay components.\n *\n * Wire the returned refs and handlers directly into the component:\n *\n * @example\n * ```ts\n * const modal = useDisclosure()\n * await saveData()\n * modal.open()\n * ```\n * ```html\n * <Modal :open=\"modal.isOpen\" @update:open=\"modal.onOpenChange\">...</Modal>\n * ```\n */\nexport function useDisclosure(defaultOpen = false): UseDisclosureReturn {\n const _isOpen = ref(defaultOpen)\n\n function open(): void {\n _isOpen.value = true\n }\n\n function close(): void {\n _isOpen.value = false\n }\n\n function toggle(): void {\n _isOpen.value = !_isOpen.value\n }\n\n function onOpenChange(value: boolean): void {\n _isOpen.value = value\n }\n\n return {\n isOpen: readonly(_isOpen),\n open,\n close,\n toggle,\n onOpenChange,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiCA,SAAgB,cAAc,cAAc,OAA4B;CACtE,MAAM,UAAU,IAAI,YAAY;CAEhC,SAAS,OAAa;AACpB,UAAQ,QAAQ;;CAGlB,SAAS,QAAc;AACrB,UAAQ,QAAQ;;CAGlB,SAAS,SAAe;AACtB,UAAQ,QAAQ,CAAC,QAAQ;;CAG3B,SAAS,aAAa,OAAsB;AAC1C,UAAQ,QAAQ;;AAGlB,QAAO;EACL,QAAQ,SAAS,QAAQ;EACzB;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
//#region src/composables/useListBox.ts
|
|
3
|
+
/**
|
|
4
|
+
* Manages selection state for the ListBox component.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const listBox = useListBox({ multiple: true, defaultSelected: ['apple'] })
|
|
9
|
+
* ```
|
|
10
|
+
* ```html
|
|
11
|
+
* <ListBox :model-value="listBox.selected" @update:model-value="listBox.onSelectionChange">
|
|
12
|
+
* <ListBoxItem value="apple">Apple</ListBoxItem>
|
|
13
|
+
* <ListBoxItem value="banana">Banana</ListBoxItem>
|
|
14
|
+
* </ListBox>
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
function useListBox(options = {}) {
|
|
18
|
+
const multiple = options.multiple ?? false;
|
|
19
|
+
const selected = ref(options.defaultSelected ?? (multiple ? [] : void 0));
|
|
20
|
+
function isSelected(key) {
|
|
21
|
+
if (Array.isArray(selected.value)) return selected.value.includes(key);
|
|
22
|
+
return selected.value === key;
|
|
23
|
+
}
|
|
24
|
+
function select(key) {
|
|
25
|
+
if (multiple) {
|
|
26
|
+
const current = selected.value ?? [];
|
|
27
|
+
if (!current.includes(key)) selected.value = [...current, key];
|
|
28
|
+
} else selected.value = key;
|
|
29
|
+
}
|
|
30
|
+
function deselect(key) {
|
|
31
|
+
if (multiple) selected.value = (selected.value ?? []).filter((k) => k !== key);
|
|
32
|
+
else if (selected.value === key) selected.value = void 0;
|
|
33
|
+
}
|
|
34
|
+
function toggle(key) {
|
|
35
|
+
if (isSelected(key)) deselect(key);
|
|
36
|
+
else select(key);
|
|
37
|
+
}
|
|
38
|
+
function selectAll(keys) {
|
|
39
|
+
if (multiple) selected.value = [...new Set(keys)];
|
|
40
|
+
}
|
|
41
|
+
function deselectAll() {
|
|
42
|
+
selected.value = multiple ? [] : void 0;
|
|
43
|
+
}
|
|
44
|
+
function onSelectionChange(value) {
|
|
45
|
+
selected.value = value;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
selected,
|
|
49
|
+
isSelected,
|
|
50
|
+
select,
|
|
51
|
+
deselect,
|
|
52
|
+
toggle,
|
|
53
|
+
selectAll,
|
|
54
|
+
deselectAll,
|
|
55
|
+
onSelectionChange
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { useListBox };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=useListBox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useListBox.js","names":[],"sources":["../../src/composables/useListBox.ts"],"sourcesContent":["import { ref, type Ref } from 'vue'\n\nexport type ListBoxValue = string | string[] | undefined\n\nexport interface UseListBoxOptions {\n /** Enable multi-selection. Defaults to false. */\n multiple?: boolean\n /** Initial selected value(s). */\n defaultSelected?: ListBoxValue\n}\n\nexport interface UseListBoxReturn {\n /** Reactive selected value(s). String in single mode, string[] in multiple mode. */\n selected: Ref<ListBoxValue>\n /** Whether a given key is currently selected. */\n isSelected: (key: string) => boolean\n /** Select an item. In single mode, replaces the current selection. */\n select: (key: string) => void\n /** Deselect an item. */\n deselect: (key: string) => void\n /** Toggle an item's selection state. */\n toggle: (key: string) => void\n /** Select all provided keys. Only effective in multiple mode. */\n selectAll: (keys: string[]) => void\n /** Clear all selections. */\n deselectAll: () => void\n /**\n * Pass as `@update:model-value` handler on the ListBox component.\n * Keeps `selected` in sync when the component changes selection internally.\n */\n onSelectionChange: (value: ListBoxValue) => void\n}\n\n/**\n * Manages selection state for the ListBox component.\n *\n * @example\n * ```ts\n * const listBox = useListBox({ multiple: true, defaultSelected: ['apple'] })\n * ```\n * ```html\n * <ListBox :model-value=\"listBox.selected\" @update:model-value=\"listBox.onSelectionChange\">\n * <ListBoxItem value=\"apple\">Apple</ListBoxItem>\n * <ListBoxItem value=\"banana\">Banana</ListBoxItem>\n * </ListBox>\n * ```\n */\nexport function useListBox(options: UseListBoxOptions = {}): UseListBoxReturn {\n const multiple = options.multiple ?? false\n\n const selected = ref<ListBoxValue>(\n options.defaultSelected ?? (multiple ? [] : undefined)\n )\n\n function isSelected(key: string): boolean {\n if (Array.isArray(selected.value)) return selected.value.includes(key)\n return selected.value === key\n }\n\n function select(key: string): void {\n if (multiple) {\n const current = (selected.value as string[]) ?? []\n if (!current.includes(key)) selected.value = [...current, key]\n } else {\n selected.value = key\n }\n }\n\n function deselect(key: string): void {\n if (multiple) {\n selected.value = ((selected.value as string[]) ?? []).filter(k => k !== key)\n } else if (selected.value === key) {\n selected.value = undefined\n }\n }\n\n function toggle(key: string): void {\n if (isSelected(key)) deselect(key)\n else select(key)\n }\n\n function selectAll(keys: string[]): void {\n if (multiple) selected.value = [...new Set(keys)]\n }\n\n function deselectAll(): void {\n selected.value = multiple ? [] : undefined\n }\n\n function onSelectionChange(value: ListBoxValue): void {\n selected.value = value\n }\n\n return {\n selected,\n isSelected,\n select,\n deselect,\n toggle,\n selectAll,\n deselectAll,\n onSelectionChange,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA+CA,SAAgB,WAAW,UAA6B,EAAE,EAAoB;CAC5E,MAAM,WAAW,QAAQ,YAAY;CAErC,MAAM,WAAW,IACf,QAAQ,oBAAoB,WAAW,EAAE,GAAG,KAAA,GAC7C;CAED,SAAS,WAAW,KAAsB;AACxC,MAAI,MAAM,QAAQ,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM,SAAS,IAAI;AACtE,SAAO,SAAS,UAAU;;CAG5B,SAAS,OAAO,KAAmB;AACjC,MAAI,UAAU;GACZ,MAAM,UAAW,SAAS,SAAsB,EAAE;AAClD,OAAI,CAAC,QAAQ,SAAS,IAAI,CAAE,UAAS,QAAQ,CAAC,GAAG,SAAS,IAAI;QAE9D,UAAS,QAAQ;;CAIrB,SAAS,SAAS,KAAmB;AACnC,MAAI,SACF,UAAS,SAAU,SAAS,SAAsB,EAAE,EAAE,QAAO,MAAK,MAAM,IAAI;WACnE,SAAS,UAAU,IAC5B,UAAS,QAAQ,KAAA;;CAIrB,SAAS,OAAO,KAAmB;AACjC,MAAI,WAAW,IAAI,CAAE,UAAS,IAAI;MAC7B,QAAO,IAAI;;CAGlB,SAAS,UAAU,MAAsB;AACvC,MAAI,SAAU,UAAS,QAAQ,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;;CAGnD,SAAS,cAAoB;AAC3B,WAAS,QAAQ,WAAW,EAAE,GAAG,KAAA;;CAGnC,SAAS,kBAAkB,OAA2B;AACpD,WAAS,QAAQ;;AAGnB,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { computed, readonly, ref } from "vue";
|
|
2
|
+
//#region src/composables/useOTP.ts
|
|
3
|
+
function useOTP(options = {}) {
|
|
4
|
+
const length = options.length ?? 6;
|
|
5
|
+
const _value = ref(options.defaultValue ?? "");
|
|
6
|
+
const isComplete = computed(() => _value.value.length === length);
|
|
7
|
+
function reset() {
|
|
8
|
+
_value.value = "";
|
|
9
|
+
}
|
|
10
|
+
function onValueChange(value) {
|
|
11
|
+
_value.value = value;
|
|
12
|
+
options.onChange?.(value);
|
|
13
|
+
}
|
|
14
|
+
function onOTPComplete(value) {
|
|
15
|
+
_value.value = value;
|
|
16
|
+
options.onComplete?.(value);
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
value: readonly(_value),
|
|
20
|
+
isComplete,
|
|
21
|
+
reset,
|
|
22
|
+
onValueChange,
|
|
23
|
+
onOTPComplete
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { useOTP };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=useOTP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOTP.js","names":[],"sources":["../../src/composables/useOTP.ts"],"sourcesContent":["import { ref, computed, readonly, type Ref, type ComputedRef } from 'vue'\n\nexport interface UseOTPOptions {\n /** Number of OTP slots. Defaults to 6. */\n length?: number\n /** Initial OTP value string. */\n defaultValue?: string\n /** Fires on every keystroke with the current value. */\n onChange?: (value: string) => void\n /** Fires when all slots are filled. */\n onComplete?: (value: string) => void\n}\n\nexport interface UseOTPReturn {\n /** The current OTP value string. */\n value: Readonly<Ref<string>>\n /** True when the value length equals the configured length. */\n isComplete: ComputedRef<boolean>\n /** Clear the OTP value. */\n reset: () => void\n /** Pass as `@update:model-value` on the InputOTP component. */\n onValueChange: (value: string) => void\n /** Pass as `@complete` on the InputOTP component. */\n onOTPComplete: (value: string) => void\n}\n\nexport function useOTP(options: UseOTPOptions = {}): UseOTPReturn {\n const length = options.length ?? 6\n const _value = ref(options.defaultValue ?? '')\n\n const isComplete = computed(() => _value.value.length === length)\n\n function reset(): void {\n _value.value = ''\n }\n\n function onValueChange(value: string): void {\n _value.value = value\n options.onChange?.(value)\n }\n\n function onOTPComplete(value: string): void {\n _value.value = value\n options.onComplete?.(value)\n }\n\n return {\n value: readonly(_value),\n isComplete,\n reset,\n onValueChange,\n onOTPComplete,\n }\n}\n"],"mappings":";;AA0BA,SAAgB,OAAO,UAAyB,EAAE,EAAgB;CAChE,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,SAAS,IAAI,QAAQ,gBAAgB,GAAG;CAE9C,MAAM,aAAa,eAAe,OAAO,MAAM,WAAW,OAAO;CAEjE,SAAS,QAAc;AACrB,SAAO,QAAQ;;CAGjB,SAAS,cAAc,OAAqB;AAC1C,SAAO,QAAQ;AACf,UAAQ,WAAW,MAAM;;CAG3B,SAAS,cAAc,OAAqB;AAC1C,SAAO,QAAQ;AACf,UAAQ,aAAa,MAAM;;AAG7B,QAAO;EACL,OAAO,SAAS,OAAO;EACvB;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { computed, ref } from "vue";
|
|
2
|
+
//#region src/composables/usePagination.ts
|
|
3
|
+
/**
|
|
4
|
+
* Manages pagination state for the Pagination component.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const pagination = usePagination({ totalItems: 200, pageSize: 20 })
|
|
9
|
+
* ```
|
|
10
|
+
* ```html
|
|
11
|
+
* <Pagination
|
|
12
|
+
* :page="pagination.page"
|
|
13
|
+
* :total-items="pagination.totalItems"
|
|
14
|
+
* :items-per-page="pagination.pageSize"
|
|
15
|
+
* @update:page="pagination.onPageChange"
|
|
16
|
+
* />
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
function usePagination(options = {}) {
|
|
20
|
+
const page = ref(options.defaultPage ?? 1);
|
|
21
|
+
const pageSize = ref(options.pageSize ?? 10);
|
|
22
|
+
const totalItems = ref(options.totalItems ?? 0);
|
|
23
|
+
const totalPages = computed(() => Math.max(1, Math.ceil(totalItems.value / pageSize.value)));
|
|
24
|
+
const isFirst = computed(() => page.value <= 1);
|
|
25
|
+
const isLast = computed(() => page.value >= totalPages.value);
|
|
26
|
+
function goToPage(p) {
|
|
27
|
+
page.value = Math.max(1, Math.min(p, totalPages.value));
|
|
28
|
+
}
|
|
29
|
+
function nextPage() {
|
|
30
|
+
if (!isLast.value) goToPage(page.value + 1);
|
|
31
|
+
}
|
|
32
|
+
function prevPage() {
|
|
33
|
+
if (!isFirst.value) goToPage(page.value - 1);
|
|
34
|
+
}
|
|
35
|
+
function onPageChange(p) {
|
|
36
|
+
goToPage(p);
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
page,
|
|
40
|
+
pageSize,
|
|
41
|
+
totalItems,
|
|
42
|
+
totalPages,
|
|
43
|
+
isFirst,
|
|
44
|
+
isLast,
|
|
45
|
+
goToPage,
|
|
46
|
+
nextPage,
|
|
47
|
+
prevPage,
|
|
48
|
+
onPageChange
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { usePagination };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=usePagination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePagination.js","names":[],"sources":["../../src/composables/usePagination.ts"],"sourcesContent":["import { ref, computed, type Ref, type ComputedRef } from 'vue'\n\nexport interface UsePaginationOptions {\n /** Total number of items across all pages. */\n totalItems?: number\n /** Number of items per page. Defaults to 10. */\n pageSize?: number\n /** Initial page for uncontrolled usage. Defaults to 1. */\n defaultPage?: number\n}\n\nexport interface UsePaginationReturn {\n /** Reactive current page number (1-based). */\n page: Ref<number>\n /** Reactive number of items per page. */\n pageSize: Ref<number>\n /** Reactive total item count. */\n totalItems: Ref<number>\n /** Computed total number of pages. Minimum 1. */\n totalPages: ComputedRef<number>\n /** Whether the current page is the first page. */\n isFirst: ComputedRef<boolean>\n /** Whether the current page is the last page. */\n isLast: ComputedRef<boolean>\n /** Navigate to a specific page number. Clamps to valid range. */\n goToPage: (page: number) => void\n /** Navigate to the next page. No-op on last page. */\n nextPage: () => void\n /** Navigate to the previous page. No-op on first page. */\n prevPage: () => void\n /**\n * Pass as `@update:page` handler on the Pagination component.\n * Keeps `page` in sync when the component navigates internally.\n */\n onPageChange: (page: number) => void\n}\n\n/**\n * Manages pagination state for the Pagination component.\n *\n * @example\n * ```ts\n * const pagination = usePagination({ totalItems: 200, pageSize: 20 })\n * ```\n * ```html\n * <Pagination\n * :page=\"pagination.page\"\n * :total-items=\"pagination.totalItems\"\n * :items-per-page=\"pagination.pageSize\"\n * @update:page=\"pagination.onPageChange\"\n * />\n * ```\n */\nexport function usePagination(options: UsePaginationOptions = {}): UsePaginationReturn {\n const page = ref(options.defaultPage ?? 1)\n const pageSize = ref(options.pageSize ?? 10)\n const totalItems = ref(options.totalItems ?? 0)\n\n const totalPages = computed(() =>\n Math.max(1, Math.ceil(totalItems.value / pageSize.value))\n )\n\n const isFirst = computed(() => page.value <= 1)\n const isLast = computed(() => page.value >= totalPages.value)\n\n function goToPage(p: number): void {\n page.value = Math.max(1, Math.min(p, totalPages.value))\n }\n\n function nextPage(): void {\n if (!isLast.value) goToPage(page.value + 1)\n }\n\n function prevPage(): void {\n if (!isFirst.value) goToPage(page.value - 1)\n }\n\n function onPageChange(p: number): void {\n goToPage(p)\n }\n\n return {\n page,\n pageSize,\n totalItems,\n totalPages,\n isFirst,\n isLast,\n goToPage,\n nextPage,\n prevPage,\n onPageChange,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqDA,SAAgB,cAAc,UAAgC,EAAE,EAAuB;CACrF,MAAM,OAAO,IAAI,QAAQ,eAAe,EAAE;CAC1C,MAAM,WAAW,IAAI,QAAQ,YAAY,GAAG;CAC5C,MAAM,aAAa,IAAI,QAAQ,cAAc,EAAE;CAE/C,MAAM,aAAa,eACjB,KAAK,IAAI,GAAG,KAAK,KAAK,WAAW,QAAQ,SAAS,MAAM,CAAC,CAC1D;CAED,MAAM,UAAU,eAAe,KAAK,SAAS,EAAE;CAC/C,MAAM,SAAS,eAAe,KAAK,SAAS,WAAW,MAAM;CAE7D,SAAS,SAAS,GAAiB;AACjC,OAAK,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,WAAW,MAAM,CAAC;;CAGzD,SAAS,WAAiB;AACxB,MAAI,CAAC,OAAO,MAAO,UAAS,KAAK,QAAQ,EAAE;;CAG7C,SAAS,WAAiB;AACxB,MAAI,CAAC,QAAQ,MAAO,UAAS,KAAK,QAAQ,EAAE;;CAG9C,SAAS,aAAa,GAAiB;AACrC,WAAS,EAAE;;AAGb,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
//#region src/composables/useRadioGroup.ts
|
|
3
|
+
/**
|
|
4
|
+
* Manages selection state for the RadioGroup component.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const radio = useRadioGroup({ defaultValue: 'option-a' })
|
|
9
|
+
* ```
|
|
10
|
+
* ```html
|
|
11
|
+
* <RadioGroup :model-value="radio.value" @update:model-value="radio.onValueChange">
|
|
12
|
+
* <Radio value="option-a">Option A</Radio>
|
|
13
|
+
* <Radio value="option-b">Option B</Radio>
|
|
14
|
+
* </RadioGroup>
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
function useRadioGroup(options = {}) {
|
|
18
|
+
const value = ref(options.defaultValue);
|
|
19
|
+
function setValue(v) {
|
|
20
|
+
value.value = v;
|
|
21
|
+
}
|
|
22
|
+
function clear() {
|
|
23
|
+
value.value = void 0;
|
|
24
|
+
}
|
|
25
|
+
function onValueChange(v) {
|
|
26
|
+
value.value = v;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
value,
|
|
30
|
+
setValue,
|
|
31
|
+
clear,
|
|
32
|
+
onValueChange
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { useRadioGroup };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=useRadioGroup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRadioGroup.js","names":[],"sources":["../../src/composables/useRadioGroup.ts"],"sourcesContent":["import { ref, type Ref } from 'vue'\n\nexport interface UseRadioGroupOptions {\n /** Initial selected value. */\n defaultValue?: string\n}\n\nexport interface UseRadioGroupReturn {\n /** Reactive selected radio value. */\n value: Ref<string | undefined>\n /** Set the selected value. */\n setValue: (value: string) => void\n /** Clear the selection. */\n clear: () => void\n /**\n * Pass as `@update:model-value` handler on the RadioGroup component.\n * Keeps `value` in sync when the component changes selection internally.\n */\n onValueChange: (value: string) => void\n}\n\n/**\n * Manages selection state for the RadioGroup component.\n *\n * @example\n * ```ts\n * const radio = useRadioGroup({ defaultValue: 'option-a' })\n * ```\n * ```html\n * <RadioGroup :model-value=\"radio.value\" @update:model-value=\"radio.onValueChange\">\n * <Radio value=\"option-a\">Option A</Radio>\n * <Radio value=\"option-b\">Option B</Radio>\n * </RadioGroup>\n * ```\n */\nexport function useRadioGroup(options: UseRadioGroupOptions = {}): UseRadioGroupReturn {\n const value = ref<string | undefined>(options.defaultValue)\n\n function setValue(v: string): void {\n value.value = v\n }\n\n function clear(): void {\n value.value = undefined\n }\n\n function onValueChange(v: string): void {\n value.value = v\n }\n\n return {\n value,\n setValue,\n clear,\n onValueChange,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmCA,SAAgB,cAAc,UAAgC,EAAE,EAAuB;CACrF,MAAM,QAAQ,IAAwB,QAAQ,aAAa;CAE3D,SAAS,SAAS,GAAiB;AACjC,QAAM,QAAQ;;CAGhB,SAAS,QAAc;AACrB,QAAM,QAAQ,KAAA;;CAGhB,SAAS,cAAc,GAAiB;AACtC,QAAM,QAAQ;;AAGhB,QAAO;EACL;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { computed, shallowRef } from "vue";
|
|
2
|
+
//#region src/composables/useRangeCalendar.ts
|
|
3
|
+
/**
|
|
4
|
+
* Manages selected date range state for the RangeCalendar component.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const range = useRangeCalendar()
|
|
9
|
+
* ```
|
|
10
|
+
* ```html
|
|
11
|
+
* <RangeCalendar v-model="range.value" />
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
function useRangeCalendar(options = {}) {
|
|
15
|
+
const value = shallowRef(options.defaultValue ?? null);
|
|
16
|
+
const start = computed(() => value.value?.start ?? null);
|
|
17
|
+
const end = computed(() => value.value?.end ?? null);
|
|
18
|
+
const isComplete = computed(() => value.value !== null && !!value.value?.start && !!value.value?.end);
|
|
19
|
+
function setRange(range) {
|
|
20
|
+
value.value = range;
|
|
21
|
+
}
|
|
22
|
+
function clearRange() {
|
|
23
|
+
value.value = null;
|
|
24
|
+
}
|
|
25
|
+
function isDisabled(date) {
|
|
26
|
+
if (options.minValue && date.compare(options.minValue) < 0) return true;
|
|
27
|
+
if (options.maxValue && date.compare(options.maxValue) > 0) return true;
|
|
28
|
+
return options.isDateDisabled?.(date) ?? false;
|
|
29
|
+
}
|
|
30
|
+
function isUnavailable(date) {
|
|
31
|
+
return options.isDateUnavailable?.(date) ?? false;
|
|
32
|
+
}
|
|
33
|
+
function onValueChange(range) {
|
|
34
|
+
value.value = range;
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
value,
|
|
38
|
+
start,
|
|
39
|
+
end,
|
|
40
|
+
isComplete,
|
|
41
|
+
setRange,
|
|
42
|
+
clearRange,
|
|
43
|
+
isDisabled,
|
|
44
|
+
isUnavailable,
|
|
45
|
+
onValueChange
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { useRangeCalendar };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=useRangeCalendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRangeCalendar.js","names":[],"sources":["../../src/composables/useRangeCalendar.ts"],"sourcesContent":["import { shallowRef, computed, type Ref, type ComputedRef } from 'vue'\nimport type { DateValue } from '@internationalized/date'\n\nexport interface DateRange {\n start: DateValue\n end: DateValue\n}\n\nexport interface UseRangeCalendarOptions {\n /** Initial selected date range for uncontrolled usage. */\n defaultValue?: DateRange | null\n /** Minimum selectable date. */\n minValue?: DateValue\n /** Maximum selectable date. */\n maxValue?: DateValue\n /** Returns true for dates that should be disabled. */\n isDateDisabled?: (date: DateValue) => boolean\n /** Returns true for dates that are unavailable. */\n isDateUnavailable?: (date: DateValue) => boolean\n}\n\nexport interface UseRangeCalendarReturn {\n /** Reactive selected date range (null when no selection). */\n value: Ref<DateRange | null>\n /** Reactive start date of the selected range. */\n start: ComputedRef<DateValue | null>\n /** Reactive end date of the selected range. */\n end: ComputedRef<DateValue | null>\n /** Whether a complete range (start and end) is selected. */\n isComplete: ComputedRef<boolean>\n /** Set the selected date range. */\n setRange: (range: DateRange) => void\n /** Clear the selected range. */\n clearRange: () => void\n /** Returns true if the given date is disabled per the `isDateDisabled` option. */\n isDisabled: (date: DateValue) => boolean\n /** Returns true if the given date is unavailable per the `isDateUnavailable` option. */\n isUnavailable: (date: DateValue) => boolean\n /**\n * Pass as `v-model` on the RangeCalendar component.\n * Keeps `value` in sync when the component changes selection internally.\n */\n onValueChange: (range: DateRange | null) => void\n}\n\n/**\n * Manages selected date range state for the RangeCalendar component.\n *\n * @example\n * ```ts\n * const range = useRangeCalendar()\n * ```\n * ```html\n * <RangeCalendar v-model=\"range.value\" />\n * ```\n */\nexport function useRangeCalendar(options: UseRangeCalendarOptions = {}): UseRangeCalendarReturn {\n const value = shallowRef<DateRange | null>(options.defaultValue ?? null)\n\n const start = computed(() => value.value?.start ?? null)\n const end = computed(() => value.value?.end ?? null)\n\n const isComplete = computed(\n () => value.value !== null && !!value.value?.start && !!value.value?.end\n )\n\n function setRange(range: DateRange): void {\n value.value = range\n }\n\n function clearRange(): void {\n value.value = null\n }\n\n function isDisabled(date: DateValue): boolean {\n if (options.minValue && date.compare(options.minValue) < 0) return true\n if (options.maxValue && date.compare(options.maxValue) > 0) return true\n return options.isDateDisabled?.(date) ?? false\n }\n\n function isUnavailable(date: DateValue): boolean {\n return options.isDateUnavailable?.(date) ?? false\n }\n\n function onValueChange(range: DateRange | null): void {\n value.value = range\n }\n\n return {\n value,\n start,\n end,\n isComplete,\n setRange,\n clearRange,\n isDisabled,\n isUnavailable,\n onValueChange,\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAwDA,SAAgB,iBAAiB,UAAmC,EAAE,EAA0B;CAC9F,MAAM,QAAQ,WAA6B,QAAQ,gBAAgB,KAAK;CAExE,MAAM,QAAQ,eAAe,MAAM,OAAO,SAAS,KAAK;CACxD,MAAM,MAAM,eAAe,MAAM,OAAO,OAAO,KAAK;CAEpD,MAAM,aAAa,eACX,MAAM,UAAU,QAAQ,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,IACtE;CAED,SAAS,SAAS,OAAwB;AACxC,QAAM,QAAQ;;CAGhB,SAAS,aAAmB;AAC1B,QAAM,QAAQ;;CAGhB,SAAS,WAAW,MAA0B;AAC5C,MAAI,QAAQ,YAAY,KAAK,QAAQ,QAAQ,SAAS,GAAG,EAAG,QAAO;AACnE,MAAI,QAAQ,YAAY,KAAK,QAAQ,QAAQ,SAAS,GAAG,EAAG,QAAO;AACnE,SAAO,QAAQ,iBAAiB,KAAK,IAAI;;CAG3C,SAAS,cAAc,MAA0B;AAC/C,SAAO,QAAQ,oBAAoB,KAAK,IAAI;;CAG9C,SAAS,cAAc,OAA+B;AACpD,QAAM,QAAQ;;AAGhB,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
|