@destyler-ui/svelte 0.0.1-beta.17 → 0.0.1-beta.21

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.
Files changed (97) hide show
  1. package/README.md +7 -1
  2. package/dist/components/aspect-ratio/components/Root.svelte +1 -2
  3. package/dist/components/aspect-ratio/hooks/use-aspect-ratio.svelte.d.ts +0 -1
  4. package/dist/components/aspect-ratio/hooks/use-aspect-ratio.svelte.js +1 -1
  5. package/dist/components/calendar/anatomy.d.ts +1 -1
  6. package/dist/components/calendar/components/Content.d.svelte.ts +1 -1
  7. package/dist/components/calendar/components/Content.svelte +2 -3
  8. package/dist/components/calendar/components/Content.svelte.d.ts +1 -1
  9. package/dist/components/calendar/components/Root.svelte +14 -8
  10. package/dist/components/calendar/hooks/use-calendar.svelte.d.ts +1 -1
  11. package/dist/components/calendar/hooks/use-calendar.svelte.js +13 -3
  12. package/dist/components/carousel/components/Root.svelte +9 -3
  13. package/dist/components/checkbox/components/Group.svelte +8 -2
  14. package/dist/components/checkbox/components/Root.svelte +8 -2
  15. package/dist/components/checkbox/hooks/use-checkbox-group.svelte.d.ts +17 -7
  16. package/dist/components/checkbox/hooks/use-checkbox-group.svelte.js +7 -4
  17. package/dist/components/checkbox/hooks/use-checkbox.svelte.js +14 -2
  18. package/dist/components/collapse/components/Root.svelte +9 -3
  19. package/dist/components/collapsible/components/Root.svelte +9 -3
  20. package/dist/components/collapsible/hooks/split-collapsible-props.svelte.d.ts +1 -1
  21. package/dist/components/collapsible/hooks/use-collapsible.svelte.d.ts +1 -1
  22. package/dist/components/color-picker/anatomy.d.ts +1 -1
  23. package/dist/components/color-picker/components/ChannelInput.svelte +9 -1
  24. package/dist/components/color-picker/components/Root.svelte +12 -4
  25. package/dist/components/color-picker/hooks/split-color-picker-props.svelte.d.ts +1 -1
  26. package/dist/components/color-picker/hooks/use-color-picker.svelte.d.ts +1 -1
  27. package/dist/components/combobox/components/Content.svelte +4 -7
  28. package/dist/components/combobox/components/Root.svelte +12 -6
  29. package/dist/components/combobox/hooks/use-combobox.svelte.d.ts +1 -1
  30. package/dist/components/combobox/hooks/use-combobox.svelte.js +13 -1
  31. package/dist/components/dialog/components/Root.svelte +10 -3
  32. package/dist/components/dialog/hooks/use-dialog.svelte.d.ts +1 -1
  33. package/dist/components/dynamic/components/Root.svelte +11 -3
  34. package/dist/components/dynamic/hooks/use-dynamic.svelte.js +26 -13
  35. package/dist/components/edit/components/Root.svelte +12 -5
  36. package/dist/components/edit/hooks/use-edit.svelte.d.ts +1 -1
  37. package/dist/components/edit/hooks/use-edit.svelte.js +25 -3
  38. package/dist/components/floating-panel/components/Root.svelte +17 -7
  39. package/dist/components/floating-panel/hooks/use-floating-panel.svelte.d.ts +1 -1
  40. package/dist/components/floating-panel/hooks/use-floating-panel.svelte.js +0 -5
  41. package/dist/components/hover-card/components/Root.svelte +9 -3
  42. package/dist/components/hover-card/hooks/use-hover-card.svelte.d.ts +1 -1
  43. package/dist/components/menu/components/CheckboxItem.svelte +9 -3
  44. package/dist/components/menu/components/RadioItemGroup.svelte +5 -2
  45. package/dist/components/menu/components/Root.svelte +9 -3
  46. package/dist/components/menu/hooks/use-menu.svelte.d.ts +1 -1
  47. package/dist/components/navigation-menu/components/Root.svelte +3 -3
  48. package/dist/components/navigation-menu/hooks/connect-navigation-menu.d.ts +10 -0
  49. package/dist/components/navigation-menu/hooks/connect-navigation-menu.js +42 -0
  50. package/dist/components/navigation-menu/hooks/use-navigation-menu.svelte.d.ts +1 -2
  51. package/dist/components/navigation-menu/hooks/use-navigation-menu.svelte.js +11 -21
  52. package/dist/components/number-input/components/Root.svelte +8 -2
  53. package/dist/components/number-input/hooks/use-number-input.svelte.js +183 -2
  54. package/dist/components/otp-input/components/Input.svelte +6 -1
  55. package/dist/components/otp-input/components/Root.svelte +8 -2
  56. package/dist/components/pagination/components/Root.svelte +14 -5
  57. package/dist/components/popover/components/Root.svelte +10 -3
  58. package/dist/components/popover/hooks/use-popover.svelte.d.ts +1 -1
  59. package/dist/components/presence/components/Presence.svelte +6 -0
  60. package/dist/components/progress/components/Root.svelte +8 -2
  61. package/dist/components/progress/hooks/use-progress.svelte.js +17 -3
  62. package/dist/components/qr-code/components/Root.svelte +8 -2
  63. package/dist/components/qr-code/hooks/use-qr-code.svelte.js +14 -4
  64. package/dist/components/radio/components/Root.svelte +9 -3
  65. package/dist/components/radio/hooks/use-radio.svelte.js +10 -1
  66. package/dist/components/scroll-area/hooks/use-scroll-area.svelte.js +0 -28
  67. package/dist/components/select/components/Root.svelte +7 -3
  68. package/dist/components/select/hooks/use-select.svelte.d.ts +1 -1
  69. package/dist/components/slider/components/DraggingIndicator.svelte +3 -3
  70. package/dist/components/slider/components/Root.svelte +8 -2
  71. package/dist/components/slider/components/ThumbPropsProvider.svelte +4 -2
  72. package/dist/components/splitter/components/Root.svelte +9 -3
  73. package/dist/components/steps/components/Root.svelte +9 -3
  74. package/dist/components/steps/hooks/split-steps-props.svelte.d.ts +1 -1
  75. package/dist/components/switch/components/Root.svelte +9 -3
  76. package/dist/components/switch/hooks/use-switch.svelte.d.ts +12 -1
  77. package/dist/components/switch/hooks/use-switch.svelte.js +10 -1
  78. package/dist/components/tabs/components/Root.svelte +9 -3
  79. package/dist/components/toggle/components/Root.svelte +8 -2
  80. package/dist/components/toggle-group/components/Root.svelte +9 -3
  81. package/dist/components/tooltip/components/Root.svelte +9 -3
  82. package/dist/components/tooltip/hooks/use-tooltip.svelte.d.ts +1 -1
  83. package/dist/components/tree/components/BranchTrigger.d.svelte.ts +2 -2
  84. package/dist/components/tree/components/BranchTrigger.svelte +3 -3
  85. package/dist/components/tree/components/BranchTrigger.svelte.d.ts +2 -2
  86. package/dist/components/tree/components/Root.svelte +8 -3
  87. package/dist/components/tree/hooks/tree-split-props.d.ts +1 -1
  88. package/dist/providers/frame/components/Content.svelte +4 -1
  89. package/dist/utils/create-machine-props.d.ts +18 -7
  90. package/dist/utils/create-machine-props.js +22 -18
  91. package/dist/utils/sync-checked.d.ts +6 -0
  92. package/dist/utils/sync-checked.js +28 -0
  93. package/dist/utils/sync-input-value.d.ts +4 -0
  94. package/dist/utils/sync-input-value.js +27 -0
  95. package/dist/utils/sync-number-input.d.ts +2 -0
  96. package/dist/utils/sync-number-input.js +45 -0
  97. package/package.json +72 -68
@@ -14,7 +14,13 @@
14
14
  import { SplitterProvider } from '../hooks/use-splitter-context'
15
15
  import { useSplitter } from '../hooks/use-splitter.svelte'
16
16
 
17
- let { size = $bindable<PanelSizeData[]>(), ...props }: SplitterRootProps = $props()
17
+ // Read the parent prop independently from the writable binding. Local writes
18
+ // notify bind: consumers without overriding ordinary controlled props.
19
+ let {
20
+ size = $bindable<PanelSizeData[]>(),
21
+ size: sizeProp,
22
+ ...props
23
+ }: SplitterRootProps = $props()
18
24
 
19
25
  const [useSplitterProps, localProps] = $derived(splitSplitterProps(props))
20
26
 
@@ -23,10 +29,10 @@
23
29
  const machineProps = $derived.by(() => ({
24
30
  ...useSplitterProps,
25
31
  id: useSplitterProps.id ?? id,
26
- size,
32
+ size: sizeProp,
27
33
  onSizeChange: (details: SizeChangeDetails) => {
28
34
  useSplitterProps.onSizeChange?.(details)
29
- if (size !== undefined) size = details.size
35
+ size = details.size
30
36
  },
31
37
  }))
32
38
 
@@ -13,7 +13,13 @@
13
13
  import { useSteps } from '../hooks/use-steps.svelte'
14
14
  import { StepsProvider } from '../hooks/use-steps-context'
15
15
 
16
- let { step = $bindable(), ...props }: StepsRootProps = $props()
16
+ // Read the parent prop independently from the writable binding. Local writes
17
+ // notify bind: consumers without overriding ordinary controlled props.
18
+ let {
19
+ step = $bindable(),
20
+ step: stepProp,
21
+ ...props
22
+ }: StepsRootProps = $props()
17
23
  const providedId = $props.id()
18
24
 
19
25
  const [useStepsProps, localProps] = $derived(splitStepsProps(props))
@@ -21,10 +27,10 @@
21
27
  const resolvedProps = $derived<UseStepsProps>({
22
28
  ...useStepsProps,
23
29
  id: useStepsProps.id ?? providedId,
24
- step,
30
+ step: stepProp,
25
31
  onStepChange(details) {
26
32
  useStepsProps.onStepChange?.(details)
27
- if (step !== undefined) step = details.step
33
+ step = details.step
28
34
  },
29
35
  })
30
36
 
@@ -1,5 +1,5 @@
1
1
  import type { Optional } from '../../../types.js';
2
2
  import type { UseStepsProps } from './use-steps.svelte.js';
3
3
  type StepsMachineProps = Optional<UseStepsProps, 'id'>;
4
- export declare function splitStepsProps<T extends StepsMachineProps>(props: T): [StepsMachineProps, Omit<T, "id" | "ids" | "step" | "orientation" | "linear" | "count" | "onStepChange" | "onStepComplete" | "defaultStep">];
4
+ export declare function splitStepsProps<T extends StepsMachineProps>(props: T): [StepsMachineProps, Omit<T, "id" | "ids" | "step" | "orientation" | "linear" | "count" | "defaultStep" | "onStepChange" | "onStepComplete">];
5
5
  export {};
@@ -13,7 +13,13 @@
13
13
  import { useSwitch } from '../hooks/use-switch.svelte'
14
14
  import { SwitchProvider } from '../hooks/use-switch-context'
15
15
 
16
- let { checked = $bindable(), ...props }: SwitchRootProps = $props()
16
+ // Read the parent prop independently from the writable binding. Local writes
17
+ // notify bind: consumers without overriding ordinary controlled props.
18
+ let {
19
+ checked = $bindable(),
20
+ checked: checkedProp,
21
+ ...props
22
+ }: SwitchRootProps = $props()
17
23
  const providedId = $props.id()
18
24
 
19
25
  const [useSwitchProps, localProps] = $derived(
@@ -37,10 +43,10 @@
37
43
  const resolvedProps = $derived<UseSwitchProps>({
38
44
  ...useSwitchProps,
39
45
  id: useSwitchProps.id ?? providedId,
40
- checked,
46
+ checked: checkedProp,
41
47
  onCheckedChange(details) {
42
48
  useSwitchProps.onCheckedChange?.(details)
43
- if (checked !== undefined) checked = details.checked
49
+ checked = details.checked
44
50
  },
45
51
  })
46
52
 
@@ -8,4 +8,15 @@ export interface UseSwitchProps extends Omit<zagSwitch.Context, 'dir' | 'getRoot
8
8
  }
9
9
  export interface UseSwitchReturn extends Accessor<zagSwitch.Api<PropTypes>> {
10
10
  }
11
- export declare function useSwitch(props: MaybeFunction<UseSwitchProps>): () => zagSwitch.Api<import("../../../utils/normalize-props.js").PropTypes>;
11
+ export declare function useSwitch(props: MaybeFunction<UseSwitchProps>): () => {
12
+ getHiddenInputProps(): Record<string, any>;
13
+ checked: boolean;
14
+ disabled: boolean | undefined;
15
+ focused: boolean | undefined;
16
+ setChecked: (checked: boolean) => void;
17
+ toggleChecked: () => void;
18
+ getRootProps: () => import("svelte/elements").HTMLLabelAttributes;
19
+ getLabelProps: () => import("svelte/elements").HTMLAttributes<HTMLElement>;
20
+ getThumbProps: () => import("svelte/elements").HTMLAttributes<HTMLElement>;
21
+ getControlProps: () => import("svelte/elements").HTMLAttributes<HTMLElement>;
22
+ };
@@ -3,6 +3,8 @@ import { useEnvironmentContext } from '../../../providers/environment/index.js';
3
3
  import { useLocaleContext } from '../../../providers/locale/index.js';
4
4
  import { createMachineProps } from '../../../utils/create-machine-props.js';
5
5
  import { normalizeProps } from '../../../utils/normalize-props.js';
6
+ import { createCheckedSync } from '../../../utils/sync-checked.js';
7
+ import { mergeProps } from '@destyler/svelte';
6
8
  import * as zagSwitch from '@destyler/switch';
7
9
  import { runIfFn } from '@destyler/utils';
8
10
  import { useFieldContext } from '../../field/index.js';
@@ -31,6 +33,13 @@ export function useSwitch(props) {
31
33
  return machineProps.context;
32
34
  },
33
35
  });
34
- const api = $derived(zagSwitch.connect(state, send, normalizeProps));
36
+ const connected = $derived(zagSwitch.connect(state, send, normalizeProps));
37
+ const syncChecked = createCheckedSync(() => connected);
38
+ const api = $derived({
39
+ ...connected,
40
+ getHiddenInputProps() {
41
+ return mergeProps(connected.getHiddenInputProps(), { onclick: syncChecked });
42
+ },
43
+ });
35
44
  return () => api;
36
45
  }
@@ -21,7 +21,13 @@
21
21
  import { TabsProvider } from '../hooks/use-tabs-context'
22
22
  import { useTabs } from '../hooks/use-tabs.svelte'
23
23
 
24
- let { value = $bindable(), ...props }: TabsRootProps = $props()
24
+ // Read the parent prop independently from the writable binding. Local writes
25
+ // notify bind: consumers without overriding ordinary controlled props.
26
+ let {
27
+ value = $bindable(),
28
+ value: valueProp,
29
+ ...props
30
+ }: TabsRootProps = $props()
25
31
 
26
32
  const [renderStrategyProps, tabsProps] = $derived(splitRenderStrategyProps(props))
27
33
 
@@ -49,10 +55,10 @@
49
55
  const machineProps = $derived.by<UseTabsProps>(() => ({
50
56
  ...useTabsProps,
51
57
  id: useTabsProps.id ?? id,
52
- value,
58
+ value: valueProp,
53
59
  onValueChange(details) {
54
60
  useTabsProps.onValueChange?.(details)
55
- if (value !== undefined) value = details.value
61
+ value = details.value
56
62
  },
57
63
  }))
58
64
 
@@ -13,7 +13,13 @@
13
13
  import { useToggle } from '../hooks/use-toggle.svelte'
14
14
  import { ToggleProvider } from '../hooks/use-toggle-context'
15
15
 
16
- let { pressed = $bindable<boolean>(), ...props }: ToggleRootProps = $props()
16
+ // Read the parent prop independently from the writable binding. Local writes
17
+ // notify bind: consumers without overriding ordinary controlled props.
18
+ let {
19
+ pressed = $bindable<boolean>(),
20
+ pressed: pressedProp,
21
+ ...props
22
+ }: ToggleRootProps = $props()
17
23
 
18
24
  const [useToggleProps, localProps] = $derived(
19
25
  createSplitProps<UseToggleProps>()(props, ['pressed', 'defaultPressed', 'disabled', 'onPressedChange']),
@@ -21,7 +27,7 @@
21
27
 
22
28
  const machineProps = $derived.by<UseToggleProps>(() => ({
23
29
  ...useToggleProps,
24
- pressed,
30
+ pressed: pressedProp,
25
31
  onPressedChange(nextPressed) {
26
32
  useToggleProps.onPressedChange?.(nextPressed)
27
33
  pressed = nextPressed
@@ -13,7 +13,13 @@
13
13
  import { ToggleGroupProvider } from '../hooks/use-toggle-group-context'
14
14
  import { useToggleGroup } from '../hooks/use-toggle-group.svelte'
15
15
 
16
- let { value = $bindable<string[]>(), ...props }: ToggleGroupRootProps = $props()
16
+ // Read the parent prop independently from the writable binding. Local writes
17
+ // notify bind: consumers without overriding ordinary controlled props.
18
+ let {
19
+ value = $bindable<string[]>(),
20
+ value: valueProp,
21
+ ...props
22
+ }: ToggleGroupRootProps = $props()
17
23
 
18
24
  const [useToggleGroupProps, localProps] = $derived(
19
25
  createSplitProps<Optional<UseToggleGroupProps, 'id'>>()(props, [
@@ -35,10 +41,10 @@
35
41
  const machineProps = $derived.by<UseToggleGroupProps>(() => ({
36
42
  ...useToggleGroupProps,
37
43
  id: useToggleGroupProps.id ?? id,
38
- value,
44
+ value: valueProp,
39
45
  onValueChange(details) {
40
46
  useToggleGroupProps.onValueChange?.(details)
41
- if (value != null) value = details.value
47
+ value = details.value
42
48
  },
43
49
  }))
44
50
 
@@ -16,7 +16,13 @@
16
16
  import { TooltipProvider } from '../hooks/use-tooltip-context'
17
17
  import { useTooltip } from '../hooks/use-tooltip.svelte'
18
18
 
19
- let { open = $bindable(), ...props }: TooltipRootProps = $props()
19
+ // Read the parent prop independently from the writable binding. Local writes
20
+ // notify bind: consumers without overriding ordinary controlled props.
21
+ let {
22
+ open = $bindable(),
23
+ open: openProp,
24
+ ...props
25
+ }: TooltipRootProps = $props()
20
26
  const providedId = $props.id()
21
27
 
22
28
  const [presenceProps, localProps] = $derived(splitPresenceProps(props))
@@ -25,10 +31,10 @@
25
31
  const resolvedProps = $derived<UseTooltipProps>({
26
32
  ...useTooltipProps,
27
33
  id: useTooltipProps.id ?? providedId,
28
- open,
34
+ open: openProp,
29
35
  onOpenChange(details) {
30
36
  useTooltipProps.onOpenChange?.(details)
31
- if (open !== undefined) open = details.open
37
+ open = details.open
32
38
  },
33
39
  })
34
40
 
@@ -2,7 +2,7 @@ import type { Accessor } from '../../../types.js';
2
2
  import type { PropTypes } from '@destyler/svelte';
3
3
  import type { MaybeFunction } from '@destyler/utils';
4
4
  import * as tooltip from '@destyler/tooltip';
5
- export interface UseTooltipProps extends Omit<tooltip.Context, 'dir' | 'getRootNode' | 'open.controlled' | 'id'> {
5
+ export interface UseTooltipProps extends Omit<tooltip.Context, 'dir' | 'getRootNode' | 'id'> {
6
6
  id: string;
7
7
  defaultOpen?: tooltip.Context['open'];
8
8
  }
@@ -1,7 +1,7 @@
1
1
  import type { Assign, HTMLProps, PolymorphicProps } from '../../../types.js';
2
- export interface TreeBranchTriggerBaseProps extends PolymorphicProps<'button'> {
2
+ export interface TreeBranchTriggerBaseProps extends PolymorphicProps<'div'> {
3
3
  }
4
- export interface TreeBranchTriggerProps extends Assign<HTMLProps<'button'>, TreeBranchTriggerBaseProps> {
4
+ export interface TreeBranchTriggerProps extends Assign<HTMLProps<'div'>, TreeBranchTriggerBaseProps> {
5
5
  }
6
6
  declare const BranchTrigger: import("svelte").Component<TreeBranchTriggerProps, {}, "">;
7
7
  type BranchTrigger = ReturnType<typeof BranchTrigger>;
@@ -1,8 +1,8 @@
1
1
  <script module lang="ts">
2
2
  import type { Assign, HTMLProps, PolymorphicProps } from '../../../types'
3
3
 
4
- export interface TreeBranchTriggerBaseProps extends PolymorphicProps<'button'> {}
5
- export interface TreeBranchTriggerProps extends Assign<HTMLProps<'button'>, TreeBranchTriggerBaseProps> {}
4
+ export interface TreeBranchTriggerBaseProps extends PolymorphicProps<'div'> {}
5
+ export interface TreeBranchTriggerProps extends Assign<HTMLProps<'div'>, TreeBranchTriggerBaseProps> {}
6
6
  </script>
7
7
 
8
8
  <script lang="ts">
@@ -19,4 +19,4 @@
19
19
  const mergedProps = $derived(mergeProps(tree().getBranchTriggerProps(nodeProps()), props))
20
20
  </script>
21
21
 
22
- <UI as="button" {...mergedProps} />
22
+ <UI as="div" {...mergedProps} />
@@ -1,7 +1,7 @@
1
1
  import type { Assign, HTMLProps, PolymorphicProps } from '../../../types.js';
2
- export interface TreeBranchTriggerBaseProps extends PolymorphicProps<'button'> {
2
+ export interface TreeBranchTriggerBaseProps extends PolymorphicProps<'div'> {
3
3
  }
4
- export interface TreeBranchTriggerProps extends Assign<HTMLProps<'button'>, TreeBranchTriggerBaseProps> {
4
+ export interface TreeBranchTriggerProps extends Assign<HTMLProps<'div'>, TreeBranchTriggerBaseProps> {
5
5
  }
6
6
  declare const BranchTrigger: import("svelte").Component<TreeBranchTriggerProps, {}, "">;
7
7
  type BranchTrigger = ReturnType<typeof BranchTrigger>;
@@ -23,10 +23,15 @@
23
23
  import { TreeProvider } from '../hooks/use-tree-context'
24
24
  import { useTree } from '../hooks/use-tree.svelte'
25
25
 
26
+ // Read the parent prop independently from the writable binding. Local writes
27
+ // notify bind: consumers without overriding ordinary controlled props.
26
28
  let {
27
29
  expandedValue = $bindable<string[]>(),
30
+ expandedValue: expandedValueProp,
28
31
  selectedValue = $bindable<string[]>(),
32
+ selectedValue: selectedValueProp,
29
33
  focusedValue = $bindable<string | null>(),
34
+ focusedValue: focusedValueProp,
30
35
  ...props
31
36
  }: TreeRootProps<T> = $props()
32
37
 
@@ -38,9 +43,9 @@
38
43
  const machineProps = $derived.by<UseTreeProps<T>>(() => ({
39
44
  ...useTreeProps,
40
45
  id: useTreeProps.id ?? id,
41
- selectedValue,
42
- expandedValue,
43
- focusedValue,
46
+ selectedValue: selectedValueProp,
47
+ expandedValue: expandedValueProp,
48
+ focusedValue: focusedValueProp,
44
49
  onExpandedChange: (details) => {
45
50
  useTreeProps.onExpandedChange?.(details)
46
51
  expandedValue = details.expandedValue
@@ -2,5 +2,5 @@ import type { Optional } from '../../../types.js';
2
2
  import type { TreeNode } from '../../collection/index.js';
3
3
  import type { UseTreeProps } from './use-tree.svelte.js';
4
4
  type TreeRootMachineProps = Optional<UseTreeProps<TreeNode>, 'id'>;
5
- export declare function splitTreeProps<T extends TreeRootMachineProps>(props: T): [TreeRootMachineProps, Omit<T, "id" | "ids" | "focusedValue" | "onFocusChange" | "selectionMode" | "collection" | "typeahead" | "expandedValue" | "selectedValue" | "onExpandedChange" | "onSelectionChange" | "expandOnClick" | "defaultSelectedValue" | "defaultExpandedValue">];
5
+ export declare function splitTreeProps<T extends TreeRootMachineProps>(props: T): [TreeRootMachineProps, Omit<T, "id" | "ids" | "focusedValue" | "onFocusChange" | "selectionMode" | "collection" | "typeahead" | "expandedValue" | "defaultExpandedValue" | "selectedValue" | "defaultSelectedValue" | "onExpandedChange" | "onSelectionChange" | "expandOnClick">];
6
6
  export {};
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte'
3
+ import { untrack } from 'svelte'
3
4
 
4
5
  interface FrameContentProps {
5
6
  onMount?(): void
@@ -10,7 +11,9 @@
10
11
  const { onMount, onUnmount, children }: FrameContentProps = $props()
11
12
 
12
13
  $effect(() => {
13
- onMount?.()
14
+ // Track callback replacement, but not state read or written by user code.
15
+ const mount = onMount
16
+ untrack(() => mount?.())
14
17
 
15
18
  return onUnmount
16
19
  })
@@ -2,14 +2,25 @@ type MachineProps = Record<string, unknown>;
2
2
  type StringKey<T> = Extract<keyof T, string>;
3
3
  type DefaultPropMap<T> = Partial<Record<StringKey<T>, StringKey<T>>>;
4
4
  /**
5
- * Separates one-time default values from the reactive machine context.
5
+ * Build machine initial + reactive context from UI props.
6
6
  *
7
- * Destyler machines read defaults when they are created, while controlled
8
- * values continue to flow through `setContext`. Keeping those two objects
9
- * separate prevents a later prop update from resetting uncontrolled state.
7
+ * Destyler 0.2.7 (Phase 3 HARD): controllable state is prop-presence based.
8
+ * Preserve core defaults without turning them into live props. A defined UI
9
+ * `open` takes priority over `defaultOpen`, including an explicit false: core
10
+ * otherwise initializes its state from defaultOpen before applying live context.
11
+ * UI-only defaults (Calendar view, Edit edit) are adapted by their own hooks.
12
+ *
13
+ * Undefined values are omitted so presence detection treats omitted live props as
14
+ * uncontrolled. Legacy `*.controlled` keys are dropped and are not forwarded to
15
+ * core. The `_defaults` / `_controlled` parameters are retained for call-site
16
+ * compatibility and are ignored.
10
17
  */
11
- export declare function createMachineProps<T extends MachineProps>(props: T, defaults?: DefaultPropMap<T>, controlled?: readonly StringKey<T>[]): {
12
- initial: MachineProps;
13
- context: MachineProps;
18
+ export declare function createMachineProps<T extends MachineProps>(props: T, _defaults?: DefaultPropMap<T>, _controlled?: readonly StringKey<T>[]): {
19
+ initial: {
20
+ [x: string]: unknown;
21
+ };
22
+ context: {
23
+ [x: string]: unknown;
24
+ };
14
25
  };
15
26
  export {};
@@ -1,23 +1,27 @@
1
1
  /**
2
- * Separates one-time default values from the reactive machine context.
2
+ * Build machine initial + reactive context from UI props.
3
3
  *
4
- * Destyler machines read defaults when they are created, while controlled
5
- * values continue to flow through `setContext`. Keeping those two objects
6
- * separate prevents a later prop update from resetting uncontrolled state.
4
+ * Destyler 0.2.7 (Phase 3 HARD): controllable state is prop-presence based.
5
+ * Preserve core defaults without turning them into live props. A defined UI
6
+ * `open` takes priority over `defaultOpen`, including an explicit false: core
7
+ * otherwise initializes its state from defaultOpen before applying live context.
8
+ * UI-only defaults (Calendar view, Edit edit) are adapted by their own hooks.
9
+ *
10
+ * Undefined values are omitted so presence detection treats omitted live props as
11
+ * uncontrolled. Legacy `*.controlled` keys are dropped and are not forwarded to
12
+ * core. The `_defaults` / `_controlled` parameters are retained for call-site
13
+ * compatibility and are ignored.
7
14
  */
8
- export function createMachineProps(props, defaults = {}, controlled = []) {
9
- const initial = { ...props };
10
- const context = { ...props };
11
- for (const [prop, defaultProp] of Object.entries(defaults)) {
12
- initial[prop] = props[prop] !== undefined ? props[prop] : props[defaultProp];
13
- delete initial[defaultProp];
14
- delete context[defaultProp];
15
- }
16
- for (const prop of controlled) {
17
- const key = `${prop}.controlled`;
18
- const isControlled = props[prop] !== undefined;
19
- initial[key] = isControlled;
20
- context[key] = isControlled;
15
+ export function createMachineProps(props, _defaults = {}, _controlled = []) {
16
+ const cleaned = {};
17
+ for (const [key, value] of Object.entries(props)) {
18
+ if (value === undefined)
19
+ continue;
20
+ if (key.endsWith('.controlled'))
21
+ continue;
22
+ cleaned[key] = value;
21
23
  }
22
- return { initial, context };
24
+ if (cleaned.open !== undefined)
25
+ delete cleaned.defaultOpen;
26
+ return { initial: { ...cleaned }, context: { ...cleaned } };
23
27
  }
@@ -0,0 +1,6 @@
1
+ /** Restore accepted state after native activation and parent bindings settle. */
2
+ export declare function createCheckedSync(getState: () => {
3
+ checked: boolean;
4
+ indeterminate?: boolean;
5
+ }): (event: Event) => Promise<void>;
6
+ export declare function createRadioCheckedSync(isChecked: (value: string) => boolean): (event: Event) => Promise<void>;
@@ -0,0 +1,28 @@
1
+ import { tick } from 'svelte';
2
+ /** Restore accepted state after native activation and parent bindings settle. */
3
+ export function createCheckedSync(getState) {
4
+ return async (event) => {
5
+ const input = event.currentTarget;
6
+ await tick();
7
+ if (!input.isConnected)
8
+ return;
9
+ const state = getState();
10
+ input.checked = state.checked;
11
+ input.indeterminate = !!state.indeterminate;
12
+ };
13
+ }
14
+ export function createRadioCheckedSync(isChecked) {
15
+ return async (event) => {
16
+ const input = event.currentTarget;
17
+ await tick();
18
+ if (!input.isConnected)
19
+ return;
20
+ // Native radio activation also unchecks the previous item. Reconcile all
21
+ // inputs owned by this group, including a previously selected sibling.
22
+ const root = input.getRootNode();
23
+ for (const item of root.querySelectorAll('input[type="radio"][data-ownedby]')) {
24
+ if (item.dataset.ownedby === input.dataset.ownedby)
25
+ item.checked = isChecked(item.value);
26
+ }
27
+ };
28
+ }
@@ -0,0 +1,4 @@
1
+ /** Reconcile a native edit that a controlled machine did not accept. */
2
+ export declare function createInputValueSync(getInputProps: () => {
3
+ value?: unknown;
4
+ }, getState: () => unknown, canSync?: () => boolean): (event: Event) => Promise<void>;
@@ -0,0 +1,27 @@
1
+ import { tick } from 'svelte';
2
+ /** Reconcile a native edit that a controlled machine did not accept. */
3
+ export function createInputValueSync(getInputProps, getState, canSync = () => true) {
4
+ let version = 0;
5
+ return async (event) => {
6
+ const currentVersion = ++version;
7
+ if (event.isComposing)
8
+ return;
9
+ const input = event.currentTarget;
10
+ const nativeValue = input.value;
11
+ const { selectionStart, selectionEnd, selectionDirection } = input;
12
+ const previousState = getState();
13
+ await tick();
14
+ if (currentVersion !== version || !canSync() || !input.isConnected || !Object.is(previousState, getState()))
15
+ return;
16
+ // Read the normalized core value after parent bindings have settled. Only
17
+ // rejected edits need reconciliation; accepted edits retain core formatting
18
+ // and partial-number behavior. Never interrupt an active IME composition.
19
+ const value = String(getInputProps().value ?? '');
20
+ if (nativeValue === value && input.value === value)
21
+ return;
22
+ if (input.value !== value)
23
+ input.value = value;
24
+ if (selectionStart !== null && selectionEnd !== null)
25
+ input.setSelectionRange(selectionStart, selectionEnd, selectionDirection ?? undefined);
26
+ };
27
+ }
@@ -0,0 +1,2 @@
1
+ /** Keep core's numeric cursor restoration, but validate ownership at RAF time. */
2
+ export declare function syncNumberInputElement(input: HTMLInputElement, value: string, canSync: () => boolean): () => void;
@@ -0,0 +1,45 @@
1
+ import { raf, setElementValue } from '@destyler/dom';
2
+ /** Keep core's numeric cursor restoration, but validate ownership at RAF time. */
3
+ export function syncNumberInputElement(input, value, canSync) {
4
+ let selection;
5
+ if (input.ownerDocument.activeElement === input) {
6
+ try {
7
+ const { selectionStart: start, selectionEnd: end } = input;
8
+ selection = {
9
+ start,
10
+ before: start === null ? '' : input.value.substring(0, start),
11
+ after: end === null ? '' : input.value.substring(end),
12
+ };
13
+ }
14
+ catch { }
15
+ }
16
+ return raf(() => {
17
+ if (!input.isConnected || !canSync() || input.value === value)
18
+ return;
19
+ setElementValue(input, value);
20
+ if (input.ownerDocument.activeElement !== input)
21
+ return;
22
+ try {
23
+ // A consumer may override the input's type. Use its resulting value and
24
+ // tolerate native types that do not support text selection, as core does.
25
+ const currentValue = input.value;
26
+ let position = currentValue.length;
27
+ if (selection?.start !== null && selection?.start !== undefined) {
28
+ const { start, before, after } = selection;
29
+ if (currentValue.endsWith(after)) {
30
+ position = currentValue.length - after.length;
31
+ }
32
+ else if (currentValue.startsWith(before)) {
33
+ position = before.length;
34
+ }
35
+ else {
36
+ const index = currentValue.indexOf(before[start - 1], start - 1);
37
+ if (index !== -1)
38
+ position = index + 1;
39
+ }
40
+ }
41
+ input.setSelectionRange(position, position);
42
+ }
43
+ catch { }
44
+ });
45
+ }