@destyler/switch 0.0.6 → 0.0.7-beta.1

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.mjs CHANGED
@@ -1,183 +1,280 @@
1
- import { defineComponent, toRefs, computed, withDirectives, h, mergeProps, withModifiers } from 'vue';
2
- import { primitiveProps, Primitive } from '@destyler/primitive';
3
- import { useVModel, useForwardExpose, useFormControl } from '@destyler/composition';
4
- import { createContext } from '@destyler/shared';
5
- import { BindOnceDirective } from '@destyler/directives';
1
+ import { createAnatomy } from '@zag-js/anatomy';
2
+ import { createScope, dataAttr, getEventTarget, visuallyHiddenStyle } from '@zag-js/dom-query';
3
+ import { isFocusVisible, trackFocusVisible } from '@zag-js/focus-visible';
4
+ import { createMachine, guards } from '@zag-js/core';
5
+ import { trackPress } from '@zag-js/dom-event';
6
+ import { trackFormControl, dispatchInputCheckedEvent } from '@zag-js/form-utils';
7
+ import { compact, isEqual, createSplitProps } from '@zag-js/utils';
8
+ import { createProps } from '@zag-js/types';
6
9
 
7
- const switchRootProps = {
8
- ...primitiveProps,
9
- /**
10
- * @default button
11
- */
12
- as: {
13
- ...primitiveProps.as,
14
- default: "button"
15
- },
16
- /**
17
- * The state of the switch when it is initially rendered.
18
- * Use when you do not need to control its state.
19
- */
20
- defaultChecked: {
21
- type: Boolean,
22
- required: false
23
- },
24
- /**
25
- * The controlled state of the switch.
26
- * Can be bind as `v-model:checked`.
27
- */
28
- checked: {
29
- type: Boolean,
30
- required: false,
31
- default: void 0
32
- },
33
- /**
34
- * When `true`, prevents the user from interacting with the switch.
35
- */
36
- disabled: {
37
- type: Boolean,
38
- required: false
39
- },
40
- /**
41
- * When `true`, indicates that the user must check the switch before the owning form can be submitted.
42
- */
43
- required: {
44
- type: Boolean,
45
- required: false
46
- },
47
- /**
48
- * The name of the switch. Submitted with its owning form as part of a name/value pair.
49
- */
50
- name: {
51
- type: String,
52
- required: false
53
- },
54
- /**
55
- * Id of the element
56
- */
57
- id: {
58
- type: String,
59
- required: false
60
- },
61
- /**
62
- * The value given as data when submitted with a `name`.
63
- */
64
- value: {
65
- type: String,
66
- required: false,
67
- default: "on"
68
- }
69
- };
70
- const switchRootEmits = {
71
- "update:checked": (_checked) => true
72
- };
73
- const [injectSwitchRootContext, provideSwitchRootContext] = createContext("DestylerSwitchRoot");
74
- const SwitchRoot = defineComponent({
75
- name: "DestylerSwitchRoot",
76
- props: switchRootProps,
77
- emits: switchRootEmits,
78
- setup(props, { emit }) {
79
- const { disabled } = toRefs(props);
80
- const checked = useVModel(props, "checked", emit, {
81
- defaultValue: props.defaultChecked,
82
- passive: props.checked === void 0
83
- });
84
- function toggleCheck() {
85
- if (disabled.value)
86
- return;
87
- checked.value = !checked.value;
88
- }
89
- const { forwardRef, currentElement } = useForwardExpose();
90
- const isFormControl = useFormControl(currentElement);
91
- const ariaLabel = computed(() => props.id && currentElement.value ? document.querySelector(`[for="${props.id}"]`)?.textContent : void 0);
92
- provideSwitchRootContext({
93
- checked,
94
- toggleCheck,
95
- disabled
96
- });
97
- return {
98
- forwardRef,
99
- toggleCheck,
100
- isFormControl,
101
- ariaLabel,
102
- checked,
103
- disabled
104
- };
105
- },
106
- render() {
107
- return [
108
- withDirectives(h(Primitive, mergeProps(this.$attrs, {
109
- "ref": (el) => this.forwardRef(el),
110
- "role": "switch",
111
- "type": this.$props.as === "button" ? "button" : void 0,
112
- "value": this.value,
113
- "aria-label": this.$attrs["aria-label"] || this.ariaLabel,
114
- "aria-checked": this.checked,
115
- "aria-required": this.$props.required,
116
- "data-state": this.checked ? "checked" : "unchecked",
117
- "data-disabled": this.disabled ? "" : void 0,
118
- "as": this.$props.as,
119
- "asChild": this.$props.asChild,
120
- "disabled": this.disabled,
121
- "onClick": () => {
122
- this.toggleCheck();
10
+ const anatomy = createAnatomy("switch").parts("root", "label", "control", "thumb");
11
+ const parts = anatomy.build();
12
+
13
+ const dom = createScope({
14
+ getRootId: (ctx) => ctx.ids?.root ?? `switch:${ctx.id}`,
15
+ getLabelId: (ctx) => ctx.ids?.label ?? `switch:${ctx.id}:label`,
16
+ getThumbId: (ctx) => ctx.ids?.thumb ?? `switch:${ctx.id}:thumb`,
17
+ getControlId: (ctx) => ctx.ids?.control ?? `switch:${ctx.id}:control`,
18
+ getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `switch:${ctx.id}:input`,
19
+ getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
20
+ getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx))
21
+ });
22
+
23
+ function connect(state, send, normalize) {
24
+ const disabled = state.context.isDisabled;
25
+ const readOnly = state.context.readOnly;
26
+ const checked = state.context.checked;
27
+ const focused = !disabled && state.context.focused;
28
+ const focusVisible = !disabled && state.context.focusVisible;
29
+ const dataAttrs = {
30
+ "data-active": dataAttr(state.context.active),
31
+ "data-focus": dataAttr(focused),
32
+ "data-focus-visible": dataAttr(focusVisible),
33
+ "data-readonly": dataAttr(readOnly),
34
+ "data-hover": dataAttr(state.context.hovered),
35
+ "data-disabled": dataAttr(disabled),
36
+ "data-state": state.context.checked ? "checked" : "unchecked",
37
+ "data-invalid": dataAttr(state.context.invalid)
38
+ };
39
+ return {
40
+ checked,
41
+ disabled,
42
+ focused,
43
+ setChecked(checked2) {
44
+ send({ type: "CHECKED.SET", checked: checked2, isTrusted: false });
45
+ },
46
+ toggleChecked() {
47
+ send({ type: "CHECKED.TOGGLE", checked, isTrusted: false });
48
+ },
49
+ getRootProps() {
50
+ return normalize.label({
51
+ ...parts.root.attrs,
52
+ ...dataAttrs,
53
+ dir: state.context.dir,
54
+ id: dom.getRootId(state.context),
55
+ htmlFor: dom.getHiddenInputId(state.context),
56
+ onPointerMove() {
57
+ if (disabled)
58
+ return;
59
+ send({ type: "CONTEXT.SET", context: { hovered: true } });
123
60
  },
124
- "onKeydown": withModifiers(() => {
125
- this.toggleCheck();
126
- }, ["enter", "prevent"])
127
- }), () => this.$slots.default?.()), [
128
- [BindOnceDirective, { id: this.$props.id }]
129
- ]),
130
- this.isFormControl ? h("input", {
61
+ onPointerLeave() {
62
+ if (disabled)
63
+ return;
64
+ send({ type: "CONTEXT.SET", context: { hovered: false } });
65
+ },
66
+ onClick(event) {
67
+ if (disabled)
68
+ return;
69
+ const target = getEventTarget(event);
70
+ if (target === dom.getHiddenInputEl(state.context)) {
71
+ event.stopPropagation();
72
+ }
73
+ }
74
+ });
75
+ },
76
+ getLabelProps() {
77
+ return normalize.element({
78
+ ...parts.label.attrs,
79
+ ...dataAttrs,
80
+ dir: state.context.dir,
81
+ id: dom.getLabelId(state.context)
82
+ });
83
+ },
84
+ getThumbProps() {
85
+ return normalize.element({
86
+ ...parts.thumb.attrs,
87
+ ...dataAttrs,
88
+ "dir": state.context.dir,
89
+ "id": dom.getThumbId(state.context),
90
+ "aria-hidden": true
91
+ });
92
+ },
93
+ getControlProps() {
94
+ return normalize.element({
95
+ ...parts.control.attrs,
96
+ ...dataAttrs,
97
+ "dir": state.context.dir,
98
+ "id": dom.getControlId(state.context),
99
+ "aria-hidden": true
100
+ });
101
+ },
102
+ getHiddenInputProps() {
103
+ return normalize.input({
104
+ "id": dom.getHiddenInputId(state.context),
131
105
  "type": "checkbox",
132
- "name": this.$props.name,
133
- "tabindex": -1,
134
- "aria-hidden": "",
135
- "disabled": this.disabled,
136
- "required": this.$props.required,
137
- "value": this.value,
138
- "checked": !!this.checked,
139
- "data-state": this.checked ? "checked" : "unchecked",
140
- "data-disabled": this.disabled ? "" : void 0,
141
- "style": {
142
- transform: "translateX(-100%)",
143
- position: "absolute",
144
- pointerEvents: "none",
145
- opacity: 0,
146
- margin: 0
106
+ "required": state.context.required,
107
+ "defaultChecked": checked,
108
+ "disabled": disabled,
109
+ "aria-labelledby": dom.getLabelId(state.context),
110
+ "aria-invalid": state.context.invalid,
111
+ "name": state.context.name,
112
+ "form": state.context.form,
113
+ "value": state.context.value,
114
+ "style": visuallyHiddenStyle,
115
+ onFocus() {
116
+ const focusVisible2 = isFocusVisible();
117
+ send({ type: "CONTEXT.SET", context: { focused: true, focusVisible: focusVisible2 } });
118
+ },
119
+ onBlur() {
120
+ send({ type: "CONTEXT.SET", context: { focused: false, focusVisible: false } });
121
+ },
122
+ onClick(event) {
123
+ if (readOnly) {
124
+ event.preventDefault();
125
+ return;
126
+ }
127
+ const checked2 = event.currentTarget.checked;
128
+ send({ type: "CHECKED.SET", checked: checked2, isTrusted: true });
147
129
  }
148
- }) : null
149
- ];
150
- }
151
- });
130
+ });
131
+ }
132
+ };
133
+ }
152
134
 
153
- const switchThumbProps = {
154
- ...primitiveProps,
155
- /**
156
- * @default span
157
- */
158
- as: {
159
- ...primitiveProps.as,
160
- default: "span"
135
+ const { not } = guards;
136
+ const invoke = {
137
+ change: (ctx) => {
138
+ ctx.onCheckedChange?.({ checked: ctx.checked });
161
139
  }
162
140
  };
163
- const SwitchThumb = defineComponent({
164
- name: "DestylerSwitchThump",
165
- props: switchThumbProps,
166
- setup(_) {
167
- const rootContext = injectSwitchRootContext();
168
- useForwardExpose();
169
- return {
170
- rootContext
171
- };
172
- },
173
- render() {
174
- return h(Primitive, {
175
- "data-state": this.rootContext.checked?.value ? "checked" : "unchecked",
176
- "data-disabled": this.rootContext.disabled.value ? "" : void 0,
177
- "asChild": this.$props.asChild,
178
- "as": this.$props.as
179
- }, () => this.$slots.default?.());
141
+ const set = {
142
+ checked: (ctx, checked) => {
143
+ if (isEqual(ctx.checked, checked))
144
+ return;
145
+ ctx.checked = checked;
146
+ invoke.change(ctx);
180
147
  }
181
- });
148
+ };
149
+ function machine(userContext) {
150
+ const ctx = compact(userContext);
151
+ return createMachine(
152
+ {
153
+ id: "switch",
154
+ initial: "ready",
155
+ context: {
156
+ checked: false,
157
+ label: "switch",
158
+ value: "on",
159
+ disabled: false,
160
+ ...ctx,
161
+ fieldsetDisabled: false,
162
+ focusVisible: false
163
+ },
164
+ computed: {
165
+ isDisabled: (ctx2) => ctx2.disabled || ctx2.fieldsetDisabled
166
+ },
167
+ watch: {
168
+ disabled: "removeFocusIfNeeded",
169
+ checked: "syncInputElement"
170
+ },
171
+ activities: ["trackFormControlState", "trackPressEvent", "trackFocusVisible"],
172
+ on: {
173
+ "CHECKED.TOGGLE": [
174
+ {
175
+ guard: not("isTrusted"),
176
+ actions: ["toggleChecked", "dispatchChangeEvent"]
177
+ },
178
+ {
179
+ actions: ["toggleChecked"]
180
+ }
181
+ ],
182
+ "CHECKED.SET": [
183
+ {
184
+ guard: not("isTrusted"),
185
+ actions: ["setChecked", "dispatchChangeEvent"]
186
+ },
187
+ {
188
+ actions: ["setChecked"]
189
+ }
190
+ ],
191
+ "CONTEXT.SET": {
192
+ actions: ["setContext"]
193
+ }
194
+ },
195
+ states: {
196
+ ready: {}
197
+ }
198
+ },
199
+ {
200
+ guards: {
201
+ isTrusted: (_ctx, evt) => !!evt.isTrusted
202
+ },
203
+ activities: {
204
+ trackPressEvent(ctx2) {
205
+ if (ctx2.isDisabled)
206
+ return;
207
+ return trackPress({
208
+ pointerNode: dom.getRootEl(ctx2),
209
+ keyboardNode: dom.getHiddenInputEl(ctx2),
210
+ isValidKey: (event) => event.key === " ",
211
+ onPress: () => ctx2.active = false,
212
+ onPressStart: () => ctx2.active = true,
213
+ onPressEnd: () => ctx2.active = false
214
+ });
215
+ },
216
+ trackFocusVisible(ctx2) {
217
+ if (ctx2.isDisabled)
218
+ return;
219
+ return trackFocusVisible({ root: dom.getRootNode(ctx2) });
220
+ },
221
+ trackFormControlState(ctx2, _evt, { send, initialContext }) {
222
+ return trackFormControl(dom.getHiddenInputEl(ctx2), {
223
+ onFieldsetDisabledChange(disabled) {
224
+ ctx2.fieldsetDisabled = disabled;
225
+ },
226
+ onFormReset() {
227
+ send({ type: "CHECKED.SET", checked: !!initialContext.checked, src: "form-reset" });
228
+ }
229
+ });
230
+ }
231
+ },
232
+ actions: {
233
+ setContext(ctx2, evt) {
234
+ Object.assign(ctx2, evt.context);
235
+ },
236
+ syncInputElement(ctx2) {
237
+ const inputEl = dom.getHiddenInputEl(ctx2);
238
+ if (!inputEl)
239
+ return;
240
+ inputEl.checked = !!ctx2.checked;
241
+ },
242
+ removeFocusIfNeeded(ctx2) {
243
+ if (ctx2.disabled && ctx2.focused) {
244
+ ctx2.focused = false;
245
+ }
246
+ },
247
+ setChecked(ctx2, evt) {
248
+ set.checked(ctx2, evt.checked);
249
+ },
250
+ toggleChecked(ctx2, _evt) {
251
+ set.checked(ctx2, !ctx2.checked);
252
+ },
253
+ dispatchChangeEvent(ctx2) {
254
+ const inputEl = dom.getHiddenInputEl(ctx2);
255
+ dispatchInputCheckedEvent(inputEl, { checked: ctx2.checked });
256
+ }
257
+ }
258
+ }
259
+ );
260
+ }
261
+
262
+ const props = createProps()([
263
+ "checked",
264
+ "dir",
265
+ "disabled",
266
+ "form",
267
+ "getRootNode",
268
+ "id",
269
+ "ids",
270
+ "invalid",
271
+ "label",
272
+ "name",
273
+ "onCheckedChange",
274
+ "readOnly",
275
+ "required",
276
+ "value"
277
+ ]);
278
+ const splitProps = createSplitProps(props);
182
279
 
183
- export { SwitchRoot, SwitchThumb, switchRootEmits, switchRootProps, switchThumbProps };
280
+ export { anatomy, connect, machine, props, splitProps };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@destyler/switch",
3
3
  "type": "module",
4
- "version": "0.0.6",
5
- "description": "a control that allows the user to toggle between checked and not checked.",
4
+ "version": "0.0.7-beta.1",
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": {
@@ -10,14 +10,6 @@
10
10
  "types": "./dist/index.d.mts",
11
11
  "default": "./dist/index.mjs"
12
12
  },
13
- "./resolver": {
14
- "types": "./dist/resolver.d.mts",
15
- "default": "./dist/resolver.mjs"
16
- },
17
- "./component": {
18
- "types": "./dist/component.d.mts",
19
- "default": "./dist/component.mjs"
20
- },
21
13
  "./*": "./*"
22
14
  },
23
15
  "main": "dist/index.cjs",
@@ -27,17 +19,19 @@
27
19
  "*.d.ts",
28
20
  "dist"
29
21
  ],
30
- "peerDependencies": {
31
- "vue": ">=3.4.21"
32
- },
33
22
  "dependencies": {
34
- "@destyler/directives": "0.0.6",
35
- "@destyler/composition": "0.0.6",
36
- "@destyler/primitive": "0.0.6",
37
- "@destyler/shared": "0.0.6"
23
+ "@zag-js/anatomy": "^0.80.0",
24
+ "@zag-js/core": "^0.80.0",
25
+ "@zag-js/dom-event": "^0.80.0",
26
+ "@zag-js/dom-query": "^0.80.0",
27
+ "@zag-js/focus-visible": "^0.80.0",
28
+ "@zag-js/form-utils": "^0.80.0",
29
+ "@zag-js/types": "^0.80.0",
30
+ "@zag-js/utils": "^0.80.0"
38
31
  },
39
32
  "scripts": {
40
33
  "clear": "rimraf ./dist",
34
+ "clear:node_modules": "rimraf ./node_modules",
41
35
  "build": "pnpm run clear && unbuild",
42
36
  "stub": "unbuild --stub"
43
37
  }
package/README.md DELETED
@@ -1,7 +0,0 @@
1
- # @destyler/switch
2
-
3
- [![NPM version](https://img.shields.io/npm/v/@destyler/switch?color=a1b858&switch=)](https://www.npmjs.com/package/@destyler/switch)
4
-
5
- > a control that allows the user to toggle between checked and not checked.
6
-
7
- [GitHub](https://github.com/destyler/destyler) | [Documentation](https://destyler-dev.zeabur.app/)
@@ -1,16 +0,0 @@
1
- 'use strict';
2
-
3
- const index = require('./index.cjs');
4
- require('vue');
5
- require('@destyler/primitive');
6
- require('@destyler/composition');
7
- require('@destyler/shared');
8
- require('@destyler/directives');
9
-
10
-
11
-
12
- exports.SwitchRoot = index.SwitchRoot;
13
- exports.SwitchThumb = index.SwitchThumb;
14
- exports.switchRootEmits = index.switchRootEmits;
15
- exports.switchRootProps = index.switchRootProps;
16
- exports.switchThumbProps = index.switchThumbProps;
@@ -1,4 +0,0 @@
1
- export { SwitchRoot, SwitchRootProps, SwitchThumb, SwitchThumbProps, switchRootEmits, switchRootProps, switchThumbProps } from './index.cjs';
2
- import 'vue';
3
- import '@destyler/primitive';
4
- import '@destyler/shared';
@@ -1,4 +0,0 @@
1
- export { SwitchRoot, SwitchRootProps, SwitchThumb, SwitchThumbProps, switchRootEmits, switchRootProps, switchThumbProps } from './index.mjs';
2
- import 'vue';
3
- import '@destyler/primitive';
4
- import '@destyler/shared';
@@ -1,4 +0,0 @@
1
- export { SwitchRoot, SwitchRootProps, SwitchThumb, SwitchThumbProps, switchRootEmits, switchRootProps, switchThumbProps } from './index.js';
2
- import 'vue';
3
- import '@destyler/primitive';
4
- import '@destyler/shared';
@@ -1,6 +0,0 @@
1
- export { SwitchRoot, SwitchThumb, switchRootEmits, switchRootProps, switchThumbProps } from './index.mjs';
2
- import 'vue';
3
- import '@destyler/primitive';
4
- import '@destyler/composition';
5
- import '@destyler/shared';
6
- import '@destyler/directives';
package/dist/resolver.cjs DELETED
@@ -1,21 +0,0 @@
1
- 'use strict';
2
-
3
- const name = "@destyler/switch";
4
-
5
- const packageName = name;
6
- const switchComponentName = [
7
- "SwitchRoot",
8
- "SwitchThumb"
9
- ];
10
- function SwitchResolver() {
11
- return {
12
- type: "component",
13
- resolve: (name2) => {
14
- if (switchComponentName.includes(name2))
15
- return { name: name2, from: packageName };
16
- }
17
- };
18
- }
19
-
20
- exports.SwitchResolver = SwitchResolver;
21
- exports.switchComponentName = switchComponentName;
@@ -1,6 +0,0 @@
1
- import { ComponentResolver } from 'unplugin-vue-components';
2
-
3
- declare const switchComponentName: string[];
4
- declare function SwitchResolver(): ComponentResolver;
5
-
6
- export { SwitchResolver, switchComponentName };
@@ -1,6 +0,0 @@
1
- import { ComponentResolver } from 'unplugin-vue-components';
2
-
3
- declare const switchComponentName: string[];
4
- declare function SwitchResolver(): ComponentResolver;
5
-
6
- export { SwitchResolver, switchComponentName };
@@ -1,6 +0,0 @@
1
- import { ComponentResolver } from 'unplugin-vue-components';
2
-
3
- declare const switchComponentName: string[];
4
- declare function SwitchResolver(): ComponentResolver;
5
-
6
- export { SwitchResolver, switchComponentName };
package/dist/resolver.mjs DELETED
@@ -1,18 +0,0 @@
1
- const name = "@destyler/switch";
2
-
3
- const packageName = name;
4
- const switchComponentName = [
5
- "SwitchRoot",
6
- "SwitchThumb"
7
- ];
8
- function SwitchResolver() {
9
- return {
10
- type: "component",
11
- resolve: (name2) => {
12
- if (switchComponentName.includes(name2))
13
- return { name: name2, from: packageName };
14
- }
15
- };
16
- }
17
-
18
- export { SwitchResolver, switchComponentName };