@fiscozen/checkbox 0.1.5 → 0.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/.eslintrc.cjs +19 -0
- package/.prettierrc.js +6 -0
- package/README.md +514 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +1031 -0
- package/coverage/coverage-final.json +7 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +131 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/coverage/src/FzCheckbox.vue.html +1489 -0
- package/coverage/src/FzCheckboxGroup.vue.html +682 -0
- package/coverage/src/common.ts.html +157 -0
- package/coverage/src/components/ErrorAlert.vue.html +268 -0
- package/coverage/src/components/FzCheckboxGroupOption.vue.html +652 -0
- package/coverage/src/components/index.html +131 -0
- package/coverage/src/index.html +161 -0
- package/coverage/src/utils.ts.html +265 -0
- package/package.json +12 -10
- package/src/FzCheckbox.vue +411 -96
- package/src/FzCheckboxGroup.vue +179 -58
- package/src/__test__/FzCheckbox.test.ts +91 -19
- package/src/__test__/FzCheckboxGroup.test.ts +167 -4
- package/src/common.ts +21 -1
- package/src/components/ErrorAlert.vue +61 -0
- package/src/components/FzCheckboxGroupOption.vue +137 -46
- package/src/index.ts +1 -0
- package/src/types.ts +166 -23
- package/src/utils.ts +60 -0
- package/tsconfig.json +1 -1
- package/dist/checkbox.js +0 -301
- package/dist/checkbox.umd.cjs +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/src/FzCheckbox.vue.d.ts +0 -95
- package/dist/src/FzCheckboxGroup.vue.d.ts +0 -70
- package/dist/src/__test__/FzCheckbox.test.d.ts +0 -1
- package/dist/src/__test__/FzCheckboxGroup.test.d.ts +0 -1
- package/dist/src/common.d.ts +0 -4
- package/dist/src/components/FzCheckboxErrorText.vue.d.ts +0 -24
- package/dist/src/components/FzCheckboxGroupOption.vue.d.ts +0 -82
- package/dist/src/index.d.ts +0 -3
- package/dist/src/types.d.ts +0 -76
- package/dist/style.css +0 -1
- package/src/components/FzCheckboxErrorText.vue +0 -20
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* ErrorAlert Component
|
|
4
|
+
*
|
|
5
|
+
* Internal component that wraps FzAlert with proper ARIA attributes for error messages.
|
|
6
|
+
* Provides accessible error announcements for screen readers.
|
|
7
|
+
*
|
|
8
|
+
* @component
|
|
9
|
+
* @internal
|
|
10
|
+
*
|
|
11
|
+
* Features:
|
|
12
|
+
* - ARIA live region with assertive priority
|
|
13
|
+
* - Automatic role="alert" for immediate announcement
|
|
14
|
+
* - Atomic reading for complete error messages
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* <ErrorAlert id="field-error" size="md">
|
|
18
|
+
* This field is required
|
|
19
|
+
* </ErrorAlert>
|
|
20
|
+
*/
|
|
21
|
+
import { FzAlert } from "@fiscozen/alert";
|
|
22
|
+
|
|
23
|
+
defineProps<{
|
|
24
|
+
/**
|
|
25
|
+
* Unique ID for the error alert element.
|
|
26
|
+
* Used for aria-describedby relationships.
|
|
27
|
+
*
|
|
28
|
+
* @example "checkbox-123-error"
|
|
29
|
+
*/
|
|
30
|
+
id: string;
|
|
31
|
+
}>();
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<!--
|
|
36
|
+
Error message display with ARIA live region
|
|
37
|
+
Announces validation errors immediately to screen readers
|
|
38
|
+
- role="alert": High-priority message
|
|
39
|
+
- aria-live="assertive": Interrupts current announcements
|
|
40
|
+
- aria-atomic="true": Reads complete message
|
|
41
|
+
|
|
42
|
+
@TODO: When FzAlert supports automatic ARIA handling based on `type`
|
|
43
|
+
(e.g., via an `announce` prop or similar semantic API), we can remove
|
|
44
|
+
these manual attributes.
|
|
45
|
+
|
|
46
|
+
Proposed future API:
|
|
47
|
+
FzAlert with type="error" and announce prop
|
|
48
|
+
would automatically get role="alert" and aria-live="assertive"
|
|
49
|
+
-->
|
|
50
|
+
<FzAlert
|
|
51
|
+
:id="id"
|
|
52
|
+
type="error"
|
|
53
|
+
alertStyle="simple"
|
|
54
|
+
role="alert"
|
|
55
|
+
aria-live="assertive"
|
|
56
|
+
aria-atomic="true"
|
|
57
|
+
size="md"
|
|
58
|
+
>
|
|
59
|
+
<slot />
|
|
60
|
+
</FzAlert>
|
|
61
|
+
</template>
|
|
@@ -1,56 +1,77 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<FzCheckbox
|
|
3
|
-
v-model="model"
|
|
4
|
-
:value="props.value"
|
|
5
|
-
:label="props.label"
|
|
6
|
-
:disabled="disabled"
|
|
7
|
-
:emphasis="emphasis"
|
|
8
|
-
:error="error"
|
|
9
|
-
:size="size"
|
|
10
|
-
:indeterminate="isIndeterminate"
|
|
11
|
-
@change="onCheckboxParentChange"
|
|
12
|
-
>
|
|
13
|
-
<template #children v-if="children?.length">
|
|
14
|
-
<div :class="[staticChildContainerClass, computedChildContainerClasses]">
|
|
15
|
-
<FzCheckbox
|
|
16
|
-
v-for="child in children"
|
|
17
|
-
:key="child.value ? child.value.toString() : child.label"
|
|
18
|
-
v-model="model"
|
|
19
|
-
:disabled="disabled"
|
|
20
|
-
v-bind="child"
|
|
21
|
-
:emphasis="emphasis"
|
|
22
|
-
:error="error"
|
|
23
|
-
:size="size"
|
|
24
|
-
@change="handleCheckboxParentChange"
|
|
25
|
-
/>
|
|
26
|
-
</div>
|
|
27
|
-
</template>
|
|
28
|
-
</FzCheckbox>
|
|
29
|
-
</template>
|
|
30
1
|
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* FzCheckboxGroupOption Component
|
|
4
|
+
*
|
|
5
|
+
* Renders a single checkbox option within a checkbox group, with support for
|
|
6
|
+
* hierarchical parent-child relationships. When children are present, the parent
|
|
7
|
+
* checkbox displays an indeterminate state when partially selected.
|
|
8
|
+
*
|
|
9
|
+
* Key features:
|
|
10
|
+
* - Automatic indeterminate state management for parent checkboxes
|
|
11
|
+
* - Bi-directional sync: parent controls children, children update parent
|
|
12
|
+
* - ARIA relationships via aria-owns for accessibility
|
|
13
|
+
* - Deterministic IDs for proper ARIA associations
|
|
14
|
+
*
|
|
15
|
+
* @component
|
|
16
|
+
* @internal Used internally by FzCheckboxGroup, not intended for direct use
|
|
17
|
+
*/
|
|
31
18
|
import { computed } from "vue";
|
|
32
19
|
import FzCheckbox from "../FzCheckbox.vue";
|
|
33
20
|
import { ParentCheckbox } from "../types";
|
|
21
|
+
import { generateCheckboxId } from "../utils";
|
|
34
22
|
|
|
35
|
-
|
|
36
|
-
MODE: 3,
|
|
37
|
-
};
|
|
23
|
+
const props = defineProps<ParentCheckbox>();
|
|
38
24
|
|
|
39
|
-
|
|
40
|
-
const currentValue = computed
|
|
25
|
+
/** The actual value used for this checkbox (falls back to label if no value provided) */
|
|
26
|
+
const currentValue = computed<string | number | boolean>(
|
|
27
|
+
() => props.value ?? props.label,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Two-way binding for selected values.
|
|
32
|
+
* Shared with parent component and all sibling checkboxes.
|
|
33
|
+
*/
|
|
41
34
|
const model = defineModel<(string | number | boolean)[]>({
|
|
42
35
|
required: true,
|
|
43
36
|
default: [],
|
|
44
37
|
});
|
|
45
38
|
|
|
46
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Unique identifier for this parent checkbox.
|
|
41
|
+
* Used as a prefix for child checkbox IDs to establish ARIA relationships.
|
|
42
|
+
*/
|
|
43
|
+
const parentId: string = generateCheckboxId();
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Computes space-separated list of child checkbox IDs.
|
|
47
|
+
* Used for aria-owns attribute to establish semantic parent-child relationship.
|
|
48
|
+
*
|
|
49
|
+
* @returns Space-separated string of child IDs, or undefined if no children
|
|
50
|
+
*/
|
|
51
|
+
const childrenIds = computed<string | undefined>(() =>
|
|
52
|
+
props.children?.map((child, index) => `${parentId}-child-${index}`).join(" "),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
/** Base layout classes for the children container (indented and vertical) */
|
|
56
|
+
const staticChildContainerClass: string =
|
|
57
|
+
"flex flex-col justify-center gap-8 pl-24";
|
|
47
58
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
props.size === "md" ? "gap-8 mt-8" : "",
|
|
51
|
-
]);
|
|
59
|
+
/** Size-specific spacing for child checkboxes */
|
|
60
|
+
const computedChildContainerClasses = computed<string[]>(() => []);
|
|
52
61
|
|
|
53
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Determines if parent checkbox should be in indeterminate state.
|
|
64
|
+
* Indeterminate means some, but not all, children are checked.
|
|
65
|
+
*
|
|
66
|
+
* States:
|
|
67
|
+
* - No children: false (not indeterminate)
|
|
68
|
+
* - No children checked: false (unchecked)
|
|
69
|
+
* - All children checked: false (fully checked)
|
|
70
|
+
* - Some children checked: true (indeterminate/partial)
|
|
71
|
+
*
|
|
72
|
+
* @returns true if parent should display indeterminate state
|
|
73
|
+
*/
|
|
74
|
+
const isIndeterminate = computed<boolean>(() => {
|
|
54
75
|
if (!props.children) return false;
|
|
55
76
|
|
|
56
77
|
const numChecked = props.children.filter((child) =>
|
|
@@ -59,33 +80,57 @@ const isIndeterminate = computed(() => {
|
|
|
59
80
|
return numChecked > 0 && numChecked < props.children.length;
|
|
60
81
|
});
|
|
61
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Handles child checkbox changes to update parent state.
|
|
85
|
+
* Called when a child checkbox is toggled.
|
|
86
|
+
*
|
|
87
|
+
* Logic:
|
|
88
|
+
* - If ALL children are now checked → add parent to selection
|
|
89
|
+
* - If ANY child is unchecked → remove parent from selection
|
|
90
|
+
*
|
|
91
|
+
* Note: Uses concat() instead of push() to ensure Vue reactivity triggers.
|
|
92
|
+
*/
|
|
62
93
|
function handleCheckboxParentChange() {
|
|
63
94
|
if (!props.children) return;
|
|
95
|
+
|
|
64
96
|
const numChecked = props.children.filter((child) =>
|
|
65
97
|
model.value.includes(child.value ?? child.label),
|
|
66
98
|
).length;
|
|
67
99
|
|
|
68
100
|
if (numChecked === props.children.length) {
|
|
69
|
-
//
|
|
70
|
-
|
|
101
|
+
// All children checked: add parent value to model if not already present
|
|
102
|
+
if (!model.value.includes(currentValue.value)) {
|
|
103
|
+
model.value = model.value.concat(currentValue.value);
|
|
104
|
+
}
|
|
71
105
|
} else {
|
|
72
|
-
// remove parent value
|
|
106
|
+
// Not all children checked: remove parent value if present
|
|
73
107
|
if (model.value.includes(currentValue.value))
|
|
74
108
|
model.value = model.value.filter((value) => value !== currentValue.value);
|
|
75
109
|
}
|
|
76
110
|
}
|
|
77
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Handles parent checkbox changes to cascade to children.
|
|
114
|
+
* Called when the parent checkbox is clicked.
|
|
115
|
+
*
|
|
116
|
+
* Cascade behavior:
|
|
117
|
+
* - Parent checked → check all children
|
|
118
|
+
* - Parent unchecked → uncheck all children
|
|
119
|
+
*
|
|
120
|
+
* Only modifies children that need changes (doesn't re-add already selected children).
|
|
121
|
+
*/
|
|
78
122
|
function onCheckboxParentChange() {
|
|
79
123
|
if (!props.children) return;
|
|
124
|
+
|
|
80
125
|
if (model.value.includes(currentValue.value)) {
|
|
81
|
-
//
|
|
126
|
+
// Parent is checked: add all unchecked children to model
|
|
82
127
|
model.value = model.value.concat(
|
|
83
128
|
props.children
|
|
84
129
|
?.map((child) => child.value ?? child.label)
|
|
85
130
|
.filter((value) => !model.value.includes(value)),
|
|
86
131
|
);
|
|
87
132
|
} else {
|
|
88
|
-
// remove all children
|
|
133
|
+
// Parent is unchecked: remove all children from model
|
|
89
134
|
model.value = model.value.filter(
|
|
90
135
|
(value) =>
|
|
91
136
|
!props.children
|
|
@@ -95,4 +140,50 @@ function onCheckboxParentChange() {
|
|
|
95
140
|
}
|
|
96
141
|
}
|
|
97
142
|
</script>
|
|
98
|
-
|
|
143
|
+
|
|
144
|
+
<template>
|
|
145
|
+
<!--
|
|
146
|
+
Parent checkbox
|
|
147
|
+
- Displays indeterminate state when children are partially selected
|
|
148
|
+
- aria-owns links to child checkboxes for screen reader navigation
|
|
149
|
+
- Change event cascades selection to all children
|
|
150
|
+
-->
|
|
151
|
+
<FzCheckbox
|
|
152
|
+
v-model="model"
|
|
153
|
+
:value="props.value"
|
|
154
|
+
:label="props.label"
|
|
155
|
+
:disabled="disabled"
|
|
156
|
+
:emphasis="emphasis"
|
|
157
|
+
:error="error"
|
|
158
|
+
:indeterminate="isIndeterminate"
|
|
159
|
+
:aria-owns="children?.length ? childrenIds : undefined"
|
|
160
|
+
@change="onCheckboxParentChange"
|
|
161
|
+
>
|
|
162
|
+
<!--
|
|
163
|
+
Children slot: renders nested child checkboxes
|
|
164
|
+
Only rendered if children array has items
|
|
165
|
+
-->
|
|
166
|
+
<template #children v-if="children?.length">
|
|
167
|
+
<!-- Indented container for visual hierarchy -->
|
|
168
|
+
<div :class="[staticChildContainerClass, computedChildContainerClasses]">
|
|
169
|
+
<!--
|
|
170
|
+
Child checkboxes
|
|
171
|
+
- Assigned deterministic IDs matching those in parent's aria-owns
|
|
172
|
+
- Change events update parent's indeterminate state
|
|
173
|
+
- Share same v-model array with parent and siblings
|
|
174
|
+
-->
|
|
175
|
+
<FzCheckbox
|
|
176
|
+
v-for="(child, index) in children"
|
|
177
|
+
:key="child.value ? child.value.toString() : child.label"
|
|
178
|
+
v-model="model"
|
|
179
|
+
:disabled="disabled"
|
|
180
|
+
v-bind="child"
|
|
181
|
+
:emphasis="emphasis"
|
|
182
|
+
:error="error"
|
|
183
|
+
:checkbox-id="`${parentId}-child-${index}`"
|
|
184
|
+
@change="handleCheckboxParentChange"
|
|
185
|
+
/>
|
|
186
|
+
</div>
|
|
187
|
+
</template>
|
|
188
|
+
</FzCheckbox>
|
|
189
|
+
</template>
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,75 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Fiscozen Checkbox component library.
|
|
3
|
+
*
|
|
4
|
+
* Provides TypeScript type definitions for checkbox components including
|
|
5
|
+
* single checkboxes, checkbox groups, and hierarchical checkbox structures.
|
|
6
|
+
*
|
|
7
|
+
* @module @fiscozen/checkbox/types
|
|
8
|
+
*/
|
|
9
|
+
import { FzTooltipProps } from "@fiscozen/tooltip";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Props for the FzCheckbox component.
|
|
13
|
+
*
|
|
14
|
+
* Supports both single-selection (boolean v-model) and multi-selection (array v-model).
|
|
15
|
+
* Can be used standalone or as part of a checkbox group.
|
|
16
|
+
*/
|
|
1
17
|
export type FzCheckboxProps = {
|
|
2
18
|
/**
|
|
3
|
-
*
|
|
19
|
+
* Text label displayed next to the checkbox.
|
|
20
|
+
* Used for aria-labelledby when not in standalone mode.
|
|
4
21
|
*/
|
|
5
22
|
label: string;
|
|
23
|
+
|
|
6
24
|
/**
|
|
7
|
-
*
|
|
25
|
+
* Value associated with the checkbox when used in array v-model.
|
|
26
|
+
* Falls back to label if not provided.
|
|
27
|
+
*
|
|
28
|
+
* @default label
|
|
8
29
|
*/
|
|
9
30
|
value?: string | number | boolean;
|
|
31
|
+
|
|
10
32
|
/**
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* If the checkbox is checked
|
|
33
|
+
* Visual size of the checkbox.
|
|
34
|
+
*
|
|
35
|
+
* @deprecated This prop is deprecated and will be removed in a future version.
|
|
36
|
+
* Checkboxes now have a fixed size equivalent to the former "md" size.
|
|
16
37
|
*/
|
|
17
|
-
|
|
38
|
+
size?: "sm" | "md";
|
|
18
39
|
/**
|
|
19
|
-
*
|
|
40
|
+
* Displays indeterminate state (partial selection).
|
|
41
|
+
* Used for parent checkboxes when some (but not all) children are selected.
|
|
42
|
+
* Screen readers announce this as "mixed" via aria-checked="mixed".
|
|
43
|
+
*
|
|
44
|
+
* @default false
|
|
20
45
|
*/
|
|
21
46
|
indeterminate?: boolean;
|
|
47
|
+
|
|
22
48
|
/**
|
|
23
|
-
*
|
|
49
|
+
* Applies emphasis styling with blue icon when checked.
|
|
50
|
+
* Highlights important or primary selection options.
|
|
51
|
+
*
|
|
52
|
+
* @default false
|
|
24
53
|
*/
|
|
25
54
|
emphasis?: boolean;
|
|
55
|
+
|
|
26
56
|
/**
|
|
27
|
-
*
|
|
57
|
+
* Disables the checkbox, preventing user interaction.
|
|
58
|
+
*
|
|
59
|
+
* @default false
|
|
28
60
|
*/
|
|
29
61
|
disabled?: boolean;
|
|
62
|
+
|
|
30
63
|
/**
|
|
31
|
-
*
|
|
64
|
+
* Shows error state with red styling.
|
|
65
|
+
* Use with error slot to display validation messages.
|
|
66
|
+
*
|
|
67
|
+
* @default false
|
|
32
68
|
*/
|
|
33
69
|
error?: boolean;
|
|
70
|
+
|
|
34
71
|
/**
|
|
35
|
-
*
|
|
72
|
+
* Marks the checkbox as required for form validation.
|
|
73
|
+
* Adds aria-required attribute for accessibility.
|
|
74
|
+
*
|
|
75
|
+
* @default false
|
|
36
76
|
*/
|
|
37
77
|
required?: boolean;
|
|
38
78
|
/**
|
|
39
|
-
*
|
|
79
|
+
* Renders only the checkbox icon without label text.
|
|
80
|
+
* Label is used for aria-label instead of being displayed.
|
|
81
|
+
* Useful for compact UIs or table cells.
|
|
82
|
+
*
|
|
83
|
+
* @default false
|
|
40
84
|
*/
|
|
41
85
|
standalone?: boolean;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Configuration for optional tooltip icon.
|
|
89
|
+
* Displays info icon next to checkbox with hover tooltip.
|
|
90
|
+
*/
|
|
91
|
+
tooltip?: FzTooltipProps;
|
|
92
|
+
/**
|
|
93
|
+
* Space-separated list of child checkbox IDs for aria-owns.
|
|
94
|
+
* Establishes semantic parent-child relationships for screen readers.
|
|
95
|
+
* Automatically managed by FzCheckboxGroupOption in hierarchical structures.
|
|
96
|
+
*
|
|
97
|
+
* @example "checkbox-child-0 checkbox-child-1 checkbox-child-2"
|
|
98
|
+
*/
|
|
99
|
+
ariaOwns?: string;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Custom ID for the checkbox input element.
|
|
103
|
+
* Auto-generated if not provided using timestamp + random suffix.
|
|
104
|
+
* Used by FzCheckboxGroupOption for deterministic ARIA relationships.
|
|
105
|
+
*
|
|
106
|
+
* @example "my-custom-checkbox-id"
|
|
107
|
+
*/
|
|
108
|
+
checkboxId?: string;
|
|
42
109
|
};
|
|
43
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Props for the FzCheckboxGroup component.
|
|
113
|
+
*
|
|
114
|
+
* Container component for managing multiple related checkboxes with shared labeling,
|
|
115
|
+
* validation, and accessibility features. Supports both flat lists and hierarchical
|
|
116
|
+
* parent-child checkbox structures with automatic indeterminate state management.
|
|
117
|
+
*/
|
|
44
118
|
export type FzCheckboxGroupProps = {
|
|
45
119
|
/**
|
|
46
|
-
*
|
|
120
|
+
* Label text for the entire checkbox group.
|
|
121
|
+
* Connected to group via aria-labelledby for screen reader accessibility.
|
|
47
122
|
*/
|
|
48
123
|
label: string;
|
|
124
|
+
|
|
49
125
|
/**
|
|
50
|
-
*
|
|
126
|
+
* Visual size for all checkboxes in the group.
|
|
127
|
+
*
|
|
128
|
+
* @deprecated This prop is deprecated and will be removed in a future version.
|
|
129
|
+
* Checkboxes now have a fixed size equivalent to the former "md" size.
|
|
51
130
|
*/
|
|
52
|
-
size
|
|
131
|
+
size?: "sm" | "md";
|
|
132
|
+
|
|
53
133
|
/**
|
|
54
|
-
*
|
|
134
|
+
* Array of checkbox options to render.
|
|
135
|
+
* Supports flat lists and hierarchical parent-child structures.
|
|
136
|
+
* Parent checkboxes automatically show indeterminate state when partially selected.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* // Flat list
|
|
140
|
+
* [
|
|
141
|
+
* { label: "Option 1", value: "opt1" },
|
|
142
|
+
* { label: "Option 2", value: "opt2" }
|
|
143
|
+
* ]
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* // Hierarchical structure
|
|
147
|
+
* [
|
|
148
|
+
* {
|
|
149
|
+
* label: "Parent",
|
|
150
|
+
* value: "parent",
|
|
151
|
+
* children: [
|
|
152
|
+
* { label: "Child 1", value: "child1" },
|
|
153
|
+
* { label: "Child 2", value: "child2" }
|
|
154
|
+
* ]
|
|
155
|
+
* }
|
|
156
|
+
* ]
|
|
55
157
|
*/
|
|
56
158
|
options: ParentCheckbox[];
|
|
159
|
+
|
|
57
160
|
/**
|
|
58
|
-
*
|
|
161
|
+
* Applies emphasis styling to all checkboxes in the group.
|
|
162
|
+
* Icons turn blue when checked.
|
|
163
|
+
*
|
|
164
|
+
* @default false
|
|
59
165
|
*/
|
|
60
166
|
emphasis?: boolean;
|
|
167
|
+
|
|
61
168
|
/**
|
|
62
|
-
*
|
|
169
|
+
* Disables all checkboxes in the group.
|
|
170
|
+
*
|
|
171
|
+
* @default false
|
|
63
172
|
*/
|
|
64
173
|
disabled?: boolean;
|
|
174
|
+
|
|
65
175
|
/**
|
|
66
|
-
*
|
|
176
|
+
* Shows error state for all checkboxes.
|
|
177
|
+
* Use with error slot to display validation messages.
|
|
178
|
+
*
|
|
179
|
+
* @default false
|
|
67
180
|
*/
|
|
68
181
|
error?: boolean;
|
|
182
|
+
|
|
69
183
|
/**
|
|
70
|
-
*
|
|
184
|
+
* Marks the group as required for form validation.
|
|
185
|
+
* Adds aria-required to the group container.
|
|
186
|
+
*
|
|
187
|
+
* @default false
|
|
71
188
|
*/
|
|
72
189
|
required?: boolean;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Arranges checkboxes horizontally instead of vertically.
|
|
193
|
+
* Useful for compact layouts or inline forms.
|
|
194
|
+
*
|
|
195
|
+
* @default false
|
|
196
|
+
*/
|
|
197
|
+
horizontal?: boolean;
|
|
73
198
|
};
|
|
74
|
-
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Checkbox option that can optionally have child checkboxes.
|
|
202
|
+
* Used for hierarchical structures with parent-child relationships.
|
|
203
|
+
* Parent checkboxes automatically display indeterminate state when children are partially selected.
|
|
204
|
+
*/
|
|
205
|
+
export type ParentCheckbox = ChildCheckbox & {
|
|
206
|
+
/**
|
|
207
|
+
* Optional array of child checkboxes for hierarchical structures.
|
|
208
|
+
* Parent shows indeterminate state when some (but not all) children are selected.
|
|
209
|
+
* Parent checkbox controls all children when toggled.
|
|
210
|
+
*/
|
|
211
|
+
children?: ChildCheckbox[];
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Individual checkbox option within a group.
|
|
216
|
+
* Inherits all FzCheckboxProps except 'size' which is controlled by the parent group.
|
|
217
|
+
*/
|
|
75
218
|
export type ChildCheckbox = Omit<FzCheckboxProps, "size">;
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for the Fiscozen Checkbox component library.
|
|
3
|
+
*
|
|
4
|
+
* @module @fiscozen/checkbox/utils
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal helper function to generate unique IDs with a given prefix.
|
|
9
|
+
*
|
|
10
|
+
* The ID is composed of:
|
|
11
|
+
* - Prefix string (e.g., "fz-checkbox", "fz-checkbox-group")
|
|
12
|
+
* - Obfuscated timestamp (Date.now() - epoch offset)
|
|
13
|
+
* - Random alphanumeric suffix (5 characters)
|
|
14
|
+
*
|
|
15
|
+
* This strategy ensures uniqueness through:
|
|
16
|
+
* - Different timestamps for components created at different times
|
|
17
|
+
* - Random suffix prevents collisions within the same millisecond
|
|
18
|
+
* - Stateless generation (no global counters to manage)
|
|
19
|
+
*
|
|
20
|
+
* @param prefix - The prefix to use for the generated ID
|
|
21
|
+
* @returns Unique ID with the specified prefix
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* generateId("fz-checkbox") // "fz-checkbox-97123456-a8d3k"
|
|
27
|
+
* generateId("fz-checkbox-group") // "fz-checkbox-group-97123457-k2m9p"
|
|
28
|
+
*/
|
|
29
|
+
function generateId(prefix: string): string {
|
|
30
|
+
// Obfuscate timestamp (Sept 13, 2020 offset) for shorter IDs
|
|
31
|
+
const timestamp = Date.now() - 1600000000000;
|
|
32
|
+
// Generate 5-char random alphanumeric suffix (base36: 0-9, a-z)
|
|
33
|
+
const random = Math.random().toString(36).slice(2, 7);
|
|
34
|
+
return `${prefix}-${timestamp}-${random}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Generates a unique ID for checkbox components.
|
|
39
|
+
*
|
|
40
|
+
* @returns Unique checkbox ID with "fz-checkbox" prefix
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* generateCheckboxId() // "fz-checkbox-97123456-a8d3k"
|
|
44
|
+
* generateCheckboxId() // "fz-checkbox-97123457-k2m9p"
|
|
45
|
+
*/
|
|
46
|
+
export function generateCheckboxId(): string {
|
|
47
|
+
return generateId("fz-checkbox");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Generates a unique ID for checkbox group components.
|
|
52
|
+
*
|
|
53
|
+
* @returns Unique checkbox group ID with "fz-checkbox-group" prefix
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* generateGroupId() // "fz-checkbox-group-97123456-b7f2n"
|
|
57
|
+
*/
|
|
58
|
+
export function generateGroupId(): string {
|
|
59
|
+
return generateId("fz-checkbox-group");
|
|
60
|
+
}
|
package/tsconfig.json
CHANGED