@destyler/switch 0.0.7-beta.7 → 0.0.7-beta.9

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/index.d.ts CHANGED
@@ -1,143 +1,147 @@
1
- import * as _zag_js_anatomy from '@zag-js/anatomy';
2
- import { DirectionProperty, CommonProperties, PropTypes, RequiredBy, NormalizeProps } from '@zag-js/types';
3
- import * as _zag_js_core from '@zag-js/core';
4
- import { StateMachine, Machine } from '@zag-js/core';
5
-
6
- declare const anatomy: _zag_js_anatomy.AnatomyInstance<"root" | "label" | "control" | "thumb">;
1
+ import * as _destyler_anatomy0 from "@destyler/anatomy";
2
+ import * as _destyler_xstate0 from "@destyler/xstate";
3
+ import { AnyEventObject, Machine, XSend, XState } from "@destyler/xstate";
4
+ import { CommonProperties, DirectionProperty, NormalizeProps, PropTypes, RequiredBy } from "@destyler/types";
7
5
 
6
+ //#region src/anatomy.d.ts
7
+ declare const anatomy: _destyler_anatomy0.AnatomyInstance<"root" | "label" | "control" | "thumb">;
8
+ //#endregion
9
+ //#region src/types.d.ts
8
10
  interface CheckedChangeDetails {
9
- checked: boolean;
11
+ checked: boolean;
10
12
  }
11
13
  type ElementIds = Partial<{
12
- root: string;
13
- hiddenInput: string;
14
- control: string;
15
- label: string;
16
- thumb: string;
14
+ root: string;
15
+ hiddenInput: string;
16
+ control: string;
17
+ label: string;
18
+ thumb: string;
17
19
  }>;
18
20
  interface PublicContext extends DirectionProperty, CommonProperties {
19
- /**
20
- * The ids of the elements in the switch. Useful for composition.
21
- */
22
- ids?: ElementIds | undefined;
23
- /**
24
- * Specifies the localized strings that identifies the accessibility elements and their states
25
- */
26
- label: string;
27
- /**
28
- * Whether the switch is disabled.
29
- */
30
- disabled?: boolean | undefined;
31
- /**
32
- * If `true`, the switch is marked as invalid.
33
- */
34
- invalid?: boolean | undefined;
35
- /**
36
- * If `true`, the switch input is marked as required,
37
- */
38
- required?: boolean | undefined;
39
- /**
40
- * Whether the switch is read-only
41
- */
42
- readOnly?: boolean | undefined;
43
- /**
44
- * Function to call when the switch is clicked.
45
- */
46
- onCheckedChange?: ((details: CheckedChangeDetails) => void) | undefined;
47
- /**
48
- * Whether the switch is checked.
49
- */
50
- checked: boolean;
51
- /**
52
- * The name of the input field in a switch
53
- * (Useful for form submission).
54
- */
55
- name?: string | undefined;
56
- /**
57
- * The id of the form that the switch belongs to
58
- */
59
- form?: string | undefined;
60
- /**
61
- * The value of switch input. Useful for form submission.
62
- * @default "on"
63
- */
64
- value?: string | number | undefined;
21
+ /**
22
+ * The ids of the elements in the switch. Useful for composition.
23
+ */
24
+ ids?: ElementIds | undefined;
25
+ /**
26
+ * Specifies the localized strings that identifies the accessibility elements and their states
27
+ */
28
+ label: string;
29
+ /**
30
+ * Whether the switch is disabled.
31
+ */
32
+ disabled?: boolean | undefined;
33
+ /**
34
+ * If `true`, the switch is marked as invalid.
35
+ */
36
+ invalid?: boolean | undefined;
37
+ /**
38
+ * If `true`, the switch input is marked as required,
39
+ */
40
+ required?: boolean | undefined;
41
+ /**
42
+ * Whether the switch is read-only
43
+ */
44
+ readOnly?: boolean | undefined;
45
+ /**
46
+ * Function to call when the switch is clicked.
47
+ */
48
+ onCheckedChange?: ((details: CheckedChangeDetails) => void) | undefined;
49
+ /**
50
+ * Whether the switch is checked.
51
+ */
52
+ checked: boolean;
53
+ /**
54
+ * The name of the input field in a switch
55
+ * (Useful for form submission).
56
+ */
57
+ name?: string | undefined;
58
+ /**
59
+ * The id of the form that the switch belongs to
60
+ */
61
+ form?: string | undefined;
62
+ /**
63
+ * The value of switch input. Useful for form submission.
64
+ * @default "on"
65
+ */
66
+ value?: string | number | undefined;
65
67
  }
66
68
  type UserDefinedContext = RequiredBy<PublicContext, 'id'>;
67
69
  type ComputedContext = Readonly<{
68
- /**
69
- * Whether the switch is disabled
70
- */
71
- isDisabled: boolean;
70
+ /**
71
+ * Whether the switch is disabled
72
+ */
73
+ isDisabled: boolean;
72
74
  }>;
73
75
  interface PrivateContext {
74
- /**
75
- * @internal
76
- * Whether the checkbox is pressed
77
- */
78
- active?: boolean | undefined;
79
- /**
80
- * @internal
81
- * Whether the checkbox has focus
82
- */
83
- focused?: boolean | undefined;
84
- /**
85
- * @internal
86
- * Whether the checkbox has focus visible
87
- */
88
- focusVisible?: boolean | undefined;
89
- /**
90
- * @internal
91
- * Whether the checkbox is hovered
92
- */
93
- hovered?: boolean | undefined;
94
- /**
95
- * @internal
96
- * Whether the checkbox fieldset is disabled
97
- */
98
- fieldsetDisabled: boolean;
99
- }
100
- interface MachineContext extends PublicContext, PrivateContext, ComputedContext {
76
+ /**
77
+ * @internal
78
+ * Whether the checkbox is pressed
79
+ */
80
+ active?: boolean | undefined;
81
+ /**
82
+ * @internal
83
+ * Whether the checkbox has focus
84
+ */
85
+ focused?: boolean | undefined;
86
+ /**
87
+ * @internal
88
+ * Whether the checkbox has focus visible
89
+ */
90
+ focusVisible?: boolean | undefined;
91
+ /**
92
+ * @internal
93
+ * Whether the checkbox is hovered
94
+ */
95
+ hovered?: boolean | undefined;
96
+ /**
97
+ * @internal
98
+ * Whether the checkbox fieldset is disabled
99
+ */
100
+ fieldsetDisabled: boolean;
101
101
  }
102
+ interface MachineContext extends PublicContext, PrivateContext, ComputedContext {}
102
103
  interface MachineState {
103
- value: 'ready';
104
+ value: 'ready';
104
105
  }
105
- type State = StateMachine.State<MachineContext, MachineState>;
106
- type Send = StateMachine.Send<StateMachine.AnyEventObject>;
107
- type Service = Machine<MachineContext, MachineState, StateMachine.AnyEventObject>;
106
+ type State = XState<MachineContext, MachineState>;
107
+ type Send = XSend<AnyEventObject>;
108
+ type Service = Machine<MachineContext, MachineState, AnyEventObject>;
108
109
  interface MachineApi<T extends PropTypes = PropTypes> {
109
- /**
110
- * Whether the checkbox is checked
111
- */
112
- checked: boolean;
113
- /**
114
- * Whether the checkbox is disabled
115
- */
116
- disabled: boolean | undefined;
117
- /**
118
- * Whether the checkbox is focused
119
- */
120
- focused: boolean | undefined;
121
- /**
122
- * Function to set the checked state of the switch.
123
- */
124
- setChecked: (checked: boolean) => void;
125
- /**
126
- * Function to toggle the checked state of the checkbox
127
- */
128
- toggleChecked: () => void;
129
- getRootProps: () => T['label'];
130
- getLabelProps: () => T['element'];
131
- getThumbProps: () => T['element'];
132
- getControlProps: () => T['element'];
133
- getHiddenInputProps: () => T['input'];
110
+ /**
111
+ * Whether the checkbox is checked
112
+ */
113
+ checked: boolean;
114
+ /**
115
+ * Whether the checkbox is disabled
116
+ */
117
+ disabled: boolean | undefined;
118
+ /**
119
+ * Whether the checkbox is focused
120
+ */
121
+ focused: boolean | undefined;
122
+ /**
123
+ * Function to set the checked state of the switch.
124
+ */
125
+ setChecked: (checked: boolean) => void;
126
+ /**
127
+ * Function to toggle the checked state of the checkbox
128
+ */
129
+ toggleChecked: () => void;
130
+ getRootProps: () => T['label'];
131
+ getLabelProps: () => T['element'];
132
+ getThumbProps: () => T['element'];
133
+ getControlProps: () => T['element'];
134
+ getHiddenInputProps: () => T['input'];
134
135
  }
135
-
136
+ //#endregion
137
+ //#region src/connect.d.ts
136
138
  declare function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T>;
137
-
138
- declare function machine(userContext: UserDefinedContext): _zag_js_core.Machine<MachineContext, MachineState, _zag_js_core.StateMachine.AnyEventObject>;
139
-
140
- declare const props: ("label" | "ids" | "disabled" | "invalid" | "required" | "readOnly" | "onCheckedChange" | "checked" | "name" | "form" | "value" | "id" | "dir" | "getRootNode")[];
141
- declare const splitProps: <Props extends Partial<UserDefinedContext>>(props: Props) => [Partial<UserDefinedContext>, Omit<Props, "label" | "ids" | "disabled" | "invalid" | "required" | "readOnly" | "onCheckedChange" | "checked" | "name" | "form" | "value" | "id" | "dir" | "getRootNode">];
142
-
143
- export { type MachineApi as Api, type CheckedChangeDetails, type UserDefinedContext as Context, type ElementIds, type Service, anatomy, connect, machine, props, splitProps };
139
+ //#endregion
140
+ //#region src/machine.d.ts
141
+ declare function machine(userContext: UserDefinedContext): _destyler_xstate0.Machine<MachineContext, MachineState, _destyler_xstate0.AnyEventObject>;
142
+ //#endregion
143
+ //#region src/props.d.ts
144
+ declare const props: ("label" | "value" | "ids" | "disabled" | "invalid" | "required" | "readOnly" | "onCheckedChange" | "checked" | "name" | "form" | "dir" | "id" | "getRootNode")[];
145
+ declare const splitProps: <Props extends Partial<UserDefinedContext>>(props: Props) => [Partial<UserDefinedContext>, Omit<Props, "label" | "value" | "ids" | "disabled" | "invalid" | "required" | "readOnly" | "onCheckedChange" | "checked" | "name" | "form" | "dir" | "id" | "getRootNode">];
146
+ //#endregion
147
+ export { type MachineApi as Api, type CheckedChangeDetails, type UserDefinedContext as Context, type ElementIds, type Service, anatomy, connect, machine, props, splitProps };
package/dist/index.js ADDED
@@ -0,0 +1,290 @@
1
+ import { createAnatomy } from "@destyler/anatomy";
2
+ import { createScope, dataAttr, dispatchInputCheckedEvent, getEventTarget, trackFormControl, trackPress, visuallyHiddenStyle } from "@destyler/dom";
3
+ import { isFocusVisible, trackFocusVisible } from "@destyler/focus-visible";
4
+ import { compact, createSplitProps, isEqual } from "@destyler/utils";
5
+ import { createMachine, guards } from "@destyler/xstate";
6
+ import { createProps } from "@destyler/types";
7
+
8
+ //#region src/anatomy.ts
9
+ const anatomy = createAnatomy("switch").parts("root", "label", "control", "thumb");
10
+ const parts = anatomy.build();
11
+
12
+ //#endregion
13
+ //#region src/dom.ts
14
+ const dom = createScope({
15
+ getRootId: (ctx) => ctx.ids?.root ?? `switch:${ctx.id}`,
16
+ getLabelId: (ctx) => ctx.ids?.label ?? `switch:${ctx.id}:label`,
17
+ getThumbId: (ctx) => ctx.ids?.thumb ?? `switch:${ctx.id}:thumb`,
18
+ getControlId: (ctx) => ctx.ids?.control ?? `switch:${ctx.id}:control`,
19
+ getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `switch:${ctx.id}:input`,
20
+ getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
21
+ getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx))
22
+ });
23
+
24
+ //#endregion
25
+ //#region src/connect.ts
26
+ function connect(state, send, normalize) {
27
+ const disabled = state.context.isDisabled;
28
+ const readOnly = state.context.readOnly;
29
+ const checked = state.context.checked;
30
+ const focused = !disabled && state.context.focused;
31
+ const focusVisible = !disabled && state.context.focusVisible;
32
+ const dataAttrs = {
33
+ "data-active": dataAttr(state.context.active),
34
+ "data-focus": dataAttr(focused),
35
+ "data-focus-visible": dataAttr(focusVisible),
36
+ "data-readonly": dataAttr(readOnly),
37
+ "data-hover": dataAttr(state.context.hovered),
38
+ "data-disabled": dataAttr(disabled),
39
+ "data-state": state.context.checked ? "checked" : "unchecked",
40
+ "data-invalid": dataAttr(state.context.invalid)
41
+ };
42
+ return {
43
+ checked,
44
+ disabled,
45
+ focused,
46
+ setChecked(checked$1) {
47
+ send({
48
+ type: "CHECKED.SET",
49
+ checked: checked$1,
50
+ isTrusted: false
51
+ });
52
+ },
53
+ toggleChecked() {
54
+ send({
55
+ type: "CHECKED.TOGGLE",
56
+ checked,
57
+ isTrusted: false
58
+ });
59
+ },
60
+ getRootProps() {
61
+ return normalize.label({
62
+ ...parts.root.attrs,
63
+ ...dataAttrs,
64
+ dir: state.context.dir,
65
+ id: dom.getRootId(state.context),
66
+ htmlFor: dom.getHiddenInputId(state.context),
67
+ onPointerMove() {
68
+ if (disabled) return;
69
+ send({
70
+ type: "CONTEXT.SET",
71
+ context: { hovered: true }
72
+ });
73
+ },
74
+ onPointerLeave() {
75
+ if (disabled) return;
76
+ send({
77
+ type: "CONTEXT.SET",
78
+ context: { hovered: false }
79
+ });
80
+ },
81
+ onClick(event) {
82
+ if (disabled) return;
83
+ const target = getEventTarget(event);
84
+ if (target === dom.getHiddenInputEl(state.context)) event.stopPropagation();
85
+ }
86
+ });
87
+ },
88
+ getLabelProps() {
89
+ return normalize.element({
90
+ ...parts.label.attrs,
91
+ ...dataAttrs,
92
+ dir: state.context.dir,
93
+ id: dom.getLabelId(state.context)
94
+ });
95
+ },
96
+ getThumbProps() {
97
+ return normalize.element({
98
+ ...parts.thumb.attrs,
99
+ ...dataAttrs,
100
+ "dir": state.context.dir,
101
+ "id": dom.getThumbId(state.context),
102
+ "aria-hidden": true
103
+ });
104
+ },
105
+ getControlProps() {
106
+ return normalize.element({
107
+ ...parts.control.attrs,
108
+ ...dataAttrs,
109
+ "dir": state.context.dir,
110
+ "id": dom.getControlId(state.context),
111
+ "aria-hidden": true
112
+ });
113
+ },
114
+ getHiddenInputProps() {
115
+ return normalize.input({
116
+ "id": dom.getHiddenInputId(state.context),
117
+ "type": "checkbox",
118
+ "required": state.context.required,
119
+ "defaultChecked": checked,
120
+ "disabled": disabled,
121
+ "aria-labelledby": dom.getLabelId(state.context),
122
+ "aria-invalid": state.context.invalid,
123
+ "name": state.context.name,
124
+ "form": state.context.form,
125
+ "value": state.context.value,
126
+ "style": visuallyHiddenStyle,
127
+ onFocus() {
128
+ const focusVisible$1 = isFocusVisible();
129
+ send({
130
+ type: "CONTEXT.SET",
131
+ context: {
132
+ focused: true,
133
+ focusVisible: focusVisible$1
134
+ }
135
+ });
136
+ },
137
+ onBlur() {
138
+ send({
139
+ type: "CONTEXT.SET",
140
+ context: {
141
+ focused: false,
142
+ focusVisible: false
143
+ }
144
+ });
145
+ },
146
+ onClick(event) {
147
+ if (readOnly) {
148
+ event.preventDefault();
149
+ return;
150
+ }
151
+ const checked$1 = event.currentTarget.checked;
152
+ send({
153
+ type: "CHECKED.SET",
154
+ checked: checked$1,
155
+ isTrusted: true
156
+ });
157
+ }
158
+ });
159
+ }
160
+ };
161
+ }
162
+
163
+ //#endregion
164
+ //#region src/machine.ts
165
+ const { not } = guards;
166
+ const invoke = { change: (ctx) => {
167
+ ctx.onCheckedChange?.({ checked: ctx.checked });
168
+ } };
169
+ const set = { checked: (ctx, checked) => {
170
+ if (isEqual(ctx.checked, checked)) return;
171
+ ctx.checked = checked;
172
+ invoke.change(ctx);
173
+ } };
174
+ function machine(userContext) {
175
+ const ctx = compact(userContext);
176
+ return createMachine({
177
+ id: "switch",
178
+ initial: "ready",
179
+ context: {
180
+ checked: false,
181
+ label: "switch",
182
+ value: "on",
183
+ disabled: false,
184
+ ...ctx,
185
+ fieldsetDisabled: false,
186
+ focusVisible: false
187
+ },
188
+ computed: { isDisabled: (ctx$1) => ctx$1.disabled || ctx$1.fieldsetDisabled },
189
+ watch: {
190
+ disabled: "removeFocusIfNeeded",
191
+ checked: "syncInputElement"
192
+ },
193
+ activities: [
194
+ "trackFormControlState",
195
+ "trackPressEvent",
196
+ "trackFocusVisible"
197
+ ],
198
+ on: {
199
+ "CHECKED.TOGGLE": [{
200
+ guard: not("isTrusted"),
201
+ actions: ["toggleChecked", "dispatchChangeEvent"]
202
+ }, { actions: ["toggleChecked"] }],
203
+ "CHECKED.SET": [{
204
+ guard: not("isTrusted"),
205
+ actions: ["setChecked", "dispatchChangeEvent"]
206
+ }, { actions: ["setChecked"] }],
207
+ "CONTEXT.SET": { actions: ["setContext"] }
208
+ },
209
+ states: { ready: {} }
210
+ }, {
211
+ guards: { isTrusted: (_ctx, evt) => !!evt.isTrusted },
212
+ activities: {
213
+ trackPressEvent(ctx$1) {
214
+ if (ctx$1.isDisabled) return;
215
+ return trackPress({
216
+ pointerNode: dom.getRootEl(ctx$1),
217
+ keyboardNode: dom.getHiddenInputEl(ctx$1),
218
+ isValidKey: (event) => event.key === " ",
219
+ onPress: () => ctx$1.active = false,
220
+ onPressStart: () => ctx$1.active = true,
221
+ onPressEnd: () => ctx$1.active = false
222
+ });
223
+ },
224
+ trackFocusVisible(ctx$1) {
225
+ if (ctx$1.isDisabled) return;
226
+ return trackFocusVisible({ root: dom.getRootNode(ctx$1) });
227
+ },
228
+ trackFormControlState(ctx$1, _evt, { send, initialContext }) {
229
+ return trackFormControl(dom.getHiddenInputEl(ctx$1), {
230
+ onFieldsetDisabledChange(disabled) {
231
+ ctx$1.fieldsetDisabled = disabled;
232
+ },
233
+ onFormReset() {
234
+ send({
235
+ type: "CHECKED.SET",
236
+ checked: !!initialContext.checked,
237
+ src: "form-reset"
238
+ });
239
+ }
240
+ });
241
+ }
242
+ },
243
+ actions: {
244
+ setContext(ctx$1, evt) {
245
+ Object.assign(ctx$1, evt.context);
246
+ },
247
+ syncInputElement(ctx$1) {
248
+ const inputEl = dom.getHiddenInputEl(ctx$1);
249
+ if (!inputEl) return;
250
+ inputEl.checked = !!ctx$1.checked;
251
+ },
252
+ removeFocusIfNeeded(ctx$1) {
253
+ if (ctx$1.disabled && ctx$1.focused) ctx$1.focused = false;
254
+ },
255
+ setChecked(ctx$1, evt) {
256
+ set.checked(ctx$1, evt.checked);
257
+ },
258
+ toggleChecked(ctx$1, _evt) {
259
+ set.checked(ctx$1, !ctx$1.checked);
260
+ },
261
+ dispatchChangeEvent(ctx$1) {
262
+ const inputEl = dom.getHiddenInputEl(ctx$1);
263
+ dispatchInputCheckedEvent(inputEl, { checked: ctx$1.checked });
264
+ }
265
+ }
266
+ });
267
+ }
268
+
269
+ //#endregion
270
+ //#region src/props.ts
271
+ const props = createProps()([
272
+ "checked",
273
+ "dir",
274
+ "disabled",
275
+ "form",
276
+ "getRootNode",
277
+ "id",
278
+ "ids",
279
+ "invalid",
280
+ "label",
281
+ "name",
282
+ "onCheckedChange",
283
+ "readOnly",
284
+ "required",
285
+ "value"
286
+ ]);
287
+ const splitProps = createSplitProps(props);
288
+
289
+ //#endregion
290
+ export { anatomy, connect, machine, props, splitProps };
package/package.json CHANGED
@@ -1,38 +1,32 @@
1
1
  {
2
2
  "name": "@destyler/switch",
3
3
  "type": "module",
4
- "version": "0.0.7-beta.7",
4
+ "version": "0.0.7-beta.9",
5
5
  "description": "A control that allows the user to toggle between checked and not checked.",
6
6
  "author": "Elone Hoo <elonehoo@gmail.com>",
7
7
  "license": "MIT",
8
8
  "exports": {
9
- ".": {
10
- "types": "./dist/index.d.mts",
11
- "default": "./dist/index.mjs"
12
- },
13
- "./*": "./*"
9
+ ".": "./dist/index.js"
14
10
  },
15
- "main": "dist/index.cjs",
16
- "module": "dist/index.mjs",
11
+ "main": "dist/index.js",
12
+ "module": "dist/index.js",
17
13
  "types": "dist/index.d.ts",
18
14
  "files": [
19
15
  "*.d.ts",
20
16
  "dist"
21
17
  ],
22
18
  "dependencies": {
23
- "@zag-js/anatomy": "^0.82.1",
24
- "@zag-js/core": "^0.82.1",
25
- "@zag-js/dom-event": "^0.80.0",
26
- "@zag-js/dom-query": "^0.82.1",
27
- "@zag-js/focus-visible": "^0.82.1",
28
- "@zag-js/form-utils": "^0.81.1",
29
- "@zag-js/types": "^0.82.1",
30
- "@zag-js/utils": "^0.82.1"
19
+ "@destyler/anatomy": "0.0.7-beta.9",
20
+ "@destyler/focus-visible": "0.0.7-beta.9",
21
+ "@destyler/dom": "0.0.7-beta.9",
22
+ "@destyler/types": "0.0.7-beta.9",
23
+ "@destyler/utils": "0.0.7-beta.9",
24
+ "@destyler/xstate": "0.0.7-beta.9"
31
25
  },
32
26
  "scripts": {
33
27
  "clear": "rimraf ./dist",
34
28
  "clear:node_modules": "rimraf ./node_modules",
35
- "build": "pnpm run clear && unbuild",
36
- "stub": "unbuild --stub"
29
+ "build": "pnpm run clear && tsdown",
30
+ "watch": "tsdown --watch"
37
31
  }
38
32
  }