@funstack/ui 0.1.0-alpha.3 → 0.1.0-alpha.5
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/accordion/accordion-root.mjs +2 -1
- package/dist/accordion/accordion-root.mjs.map +1 -1
- package/dist/combobox/combobox-clear.mjs +2 -1
- package/dist/combobox/combobox-clear.mjs.map +1 -1
- package/dist/combobox/combobox-list.mjs +2 -1
- package/dist/combobox/combobox-list.mjs.map +1 -1
- package/dist/combobox/combobox-popup.d.mts.map +1 -1
- package/dist/combobox/combobox-popup.mjs +7 -2
- package/dist/combobox/combobox-popup.mjs.map +1 -1
- package/dist/combobox/combobox-root.mjs +1 -1
- package/dist/combobox/combobox-trigger.mjs +2 -1
- package/dist/combobox/combobox-trigger.mjs.map +1 -1
- package/dist/dialog/dialog-close.mjs +2 -1
- package/dist/dialog/dialog-close.mjs.map +1 -1
- package/dist/dialog/dialog-form.d.mts +14 -8
- package/dist/dialog/dialog-form.d.mts.map +1 -1
- package/dist/dialog/dialog-form.mjs +36 -5
- package/dist/dialog/dialog-form.mjs.map +1 -1
- package/dist/dialog/dialog-popup.d.mts.map +1 -1
- package/dist/dialog/dialog-popup.mjs +13 -5
- package/dist/dialog/dialog-popup.mjs.map +1 -1
- package/dist/dialog/dialog-root.mjs +1 -1
- package/dist/dialog/dialog-trigger.mjs +2 -1
- package/dist/dialog/dialog-trigger.mjs.map +1 -1
- package/dist/field/field-root.mjs +5 -3
- package/dist/field/field-root.mjs.map +1 -1
- package/dist/form/form-root.mjs +2 -1
- package/dist/form/form-root.mjs.map +1 -1
- package/dist/form/form-submit.mjs +2 -1
- package/dist/form/form-submit.mjs.map +1 -1
- package/dist/index.d.mts +27 -1
- package/dist/index.mjs +6 -1
- package/dist/internal/announce.mjs +53 -0
- package/dist/internal/announce.mjs.map +1 -0
- package/dist/internal/decimal.mjs +27 -0
- package/dist/internal/decimal.mjs.map +1 -0
- package/dist/internal/dev-warn.mjs +17 -0
- package/dist/internal/dev-warn.mjs.map +1 -0
- package/dist/internal/field-context.mjs.map +1 -1
- package/dist/internal/range-value.mjs +51 -0
- package/dist/internal/range-value.mjs.map +1 -0
- package/dist/internal/render-element.mjs +54 -0
- package/dist/internal/render-element.mjs.map +1 -0
- package/dist/internal/toolbar-context.mjs +17 -0
- package/dist/internal/toolbar-context.mjs.map +1 -0
- package/dist/internal/use-exit-animation.mjs +26 -6
- package/dist/internal/use-exit-animation.mjs.map +1 -1
- package/dist/internal/use-field-control.mjs +5 -3
- package/dist/internal/use-field-control.mjs.map +1 -1
- package/dist/internal/use-popover-popup.mjs +3 -2
- package/dist/internal/use-popover-popup.mjs.map +1 -1
- package/dist/internal/use-popover-trigger.mjs +1 -1
- package/dist/internal/use-render.mjs +11 -34
- package/dist/internal/use-render.mjs.map +1 -1
- package/dist/internal/use-roving-focus.mjs +301 -0
- package/dist/internal/use-roving-focus.mjs.map +1 -0
- package/dist/menu/menu-checkbox-item.mjs +2 -1
- package/dist/menu/menu-checkbox-item.mjs.map +1 -1
- package/dist/menu/menu-item.mjs +2 -1
- package/dist/menu/menu-item.mjs.map +1 -1
- package/dist/menu/menu-popup.d.mts.map +1 -1
- package/dist/menu/menu-popup.mjs +7 -2
- package/dist/menu/menu-popup.mjs.map +1 -1
- package/dist/menu/menu-radio-item.mjs +2 -1
- package/dist/menu/menu-radio-item.mjs.map +1 -1
- package/dist/menu/menu-root.mjs +1 -1
- package/dist/menu/menu-trigger.d.mts +2 -1
- package/dist/menu/menu-trigger.d.mts.map +1 -1
- package/dist/menu/menu-trigger.mjs +15 -4
- package/dist/menu/menu-trigger.mjs.map +1 -1
- package/dist/meter/index.d.mts +24 -0
- package/dist/meter/index.d.mts.map +1 -0
- package/dist/meter/index.mjs +23 -0
- package/dist/meter/index.mjs.map +1 -0
- package/dist/meter/meter-context.mjs +13 -0
- package/dist/meter/meter-context.mjs.map +1 -0
- package/dist/meter/meter-indicator.d.mts +19 -0
- package/dist/meter/meter-indicator.d.mts.map +1 -0
- package/dist/meter/meter-indicator.mjs +25 -0
- package/dist/meter/meter-indicator.mjs.map +1 -0
- package/dist/meter/meter-label.d.mts +19 -0
- package/dist/meter/meter-label.d.mts.map +1 -0
- package/dist/meter/meter-label.mjs +28 -0
- package/dist/meter/meter-label.mjs.map +1 -0
- package/dist/meter/meter-region.d.mts +4 -0
- package/dist/meter/meter-region.d.mts.map +1 -0
- package/dist/meter/meter-region.mjs +39 -0
- package/dist/meter/meter-region.mjs.map +1 -0
- package/dist/meter/meter-root.d.mts +71 -0
- package/dist/meter/meter-root.d.mts.map +1 -0
- package/dist/meter/meter-root.mjs +83 -0
- package/dist/meter/meter-root.mjs.map +1 -0
- package/dist/meter/meter-track.d.mts +19 -0
- package/dist/meter/meter-track.d.mts.map +1 -0
- package/dist/meter/meter-track.mjs +25 -0
- package/dist/meter/meter-track.mjs.map +1 -0
- package/dist/meter/meter-value.d.mts +20 -0
- package/dist/meter/meter-value.d.mts.map +1 -0
- package/dist/meter/meter-value.mjs +29 -0
- package/dist/meter/meter-value.mjs.map +1 -0
- package/dist/number-field/index.d.mts +26 -0
- package/dist/number-field/index.d.mts.map +1 -0
- package/dist/number-field/index.mjs +26 -0
- package/dist/number-field/index.mjs.map +1 -0
- package/dist/number-field/number-field-arithmetic.mjs +78 -0
- package/dist/number-field/number-field-arithmetic.mjs.map +1 -0
- package/dist/number-field/number-field-context.d.mts +2 -0
- package/dist/number-field/number-field-context.mjs +13 -0
- package/dist/number-field/number-field-context.mjs.map +1 -0
- package/dist/number-field/number-field-decrement.d.mts +16 -0
- package/dist/number-field/number-field-decrement.d.mts.map +1 -0
- package/dist/number-field/number-field-decrement.mjs +19 -0
- package/dist/number-field/number-field-decrement.mjs.map +1 -0
- package/dist/number-field/number-field-format.mjs +279 -0
- package/dist/number-field/number-field-format.mjs.map +1 -0
- package/dist/number-field/number-field-increment.d.mts +32 -0
- package/dist/number-field/number-field-increment.d.mts.map +1 -0
- package/dist/number-field/number-field-increment.mjs +68 -0
- package/dist/number-field/number-field-increment.mjs.map +1 -0
- package/dist/number-field/number-field-input.d.mts +29 -0
- package/dist/number-field/number-field-input.d.mts.map +1 -0
- package/dist/number-field/number-field-input.mjs +163 -0
- package/dist/number-field/number-field-input.mjs.map +1 -0
- package/dist/number-field/number-field-label.d.mts +23 -0
- package/dist/number-field/number-field-label.d.mts.map +1 -0
- package/dist/number-field/number-field-label.mjs +47 -0
- package/dist/number-field/number-field-label.mjs.map +1 -0
- package/dist/number-field/number-field-root.d.mts +108 -0
- package/dist/number-field/number-field-root.d.mts.map +1 -0
- package/dist/number-field/number-field-root.mjs +523 -0
- package/dist/number-field/number-field-root.mjs.map +1 -0
- package/dist/number-field/use-step-button.mjs +107 -0
- package/dist/number-field/use-step-button.mjs.map +1 -0
- package/dist/popover/popover-close.mjs +2 -1
- package/dist/popover/popover-close.mjs.map +1 -1
- package/dist/popover/popover-popup.d.mts.map +1 -1
- package/dist/popover/popover-popup.mjs +7 -2
- package/dist/popover/popover-popup.mjs.map +1 -1
- package/dist/popover/popover-root.mjs +1 -1
- package/dist/progress/index.d.mts +24 -0
- package/dist/progress/index.d.mts.map +1 -0
- package/dist/progress/index.mjs +24 -0
- package/dist/progress/index.mjs.map +1 -0
- package/dist/progress/progress-context.mjs +13 -0
- package/dist/progress/progress-context.mjs.map +1 -0
- package/dist/progress/progress-indicator.d.mts +19 -0
- package/dist/progress/progress-indicator.d.mts.map +1 -0
- package/dist/progress/progress-indicator.mjs +29 -0
- package/dist/progress/progress-indicator.mjs.map +1 -0
- package/dist/progress/progress-label.d.mts +19 -0
- package/dist/progress/progress-label.d.mts.map +1 -0
- package/dist/progress/progress-label.mjs +30 -0
- package/dist/progress/progress-label.mjs.map +1 -0
- package/dist/progress/progress-root.d.mts +68 -0
- package/dist/progress/progress-root.d.mts.map +1 -0
- package/dist/progress/progress-root.mjs +80 -0
- package/dist/progress/progress-root.mjs.map +1 -0
- package/dist/progress/progress-track.d.mts +19 -0
- package/dist/progress/progress-track.d.mts.map +1 -0
- package/dist/progress/progress-track.mjs +29 -0
- package/dist/progress/progress-track.mjs.map +1 -0
- package/dist/progress/progress-value.d.mts +20 -0
- package/dist/progress/progress-value.d.mts.map +1 -0
- package/dist/progress/progress-value.mjs +33 -0
- package/dist/progress/progress-value.mjs.map +1 -0
- package/dist/slider/slider-arithmetic.mjs +1 -17
- package/dist/slider/slider-arithmetic.mjs.map +1 -1
- package/dist/slider/slider-root.mjs +3 -2
- package/dist/slider/slider-root.mjs.map +1 -1
- package/dist/slider/slider-thumb.mjs +2 -1
- package/dist/slider/slider-thumb.mjs.map +1 -1
- package/dist/slider/slider-track.mjs +2 -1
- package/dist/slider/slider-track.mjs.map +1 -1
- package/dist/tabs/tabs-indicator.mjs +2 -1
- package/dist/tabs/tabs-indicator.mjs.map +1 -1
- package/dist/tabs/tabs-tab.mjs +2 -1
- package/dist/tabs/tabs-tab.mjs.map +1 -1
- package/dist/toast/toast-action.mjs +2 -1
- package/dist/toast/toast-action.mjs.map +1 -1
- package/dist/toast/toast-close.mjs +2 -1
- package/dist/toast/toast-close.mjs.map +1 -1
- package/dist/toast/toast-root.mjs +3 -2
- package/dist/toast/toast-root.mjs.map +1 -1
- package/dist/toast/toast-viewport.d.mts.map +1 -1
- package/dist/toast/toast-viewport.mjs +30 -7
- package/dist/toast/toast-viewport.mjs.map +1 -1
- package/dist/toast/toast.d.mts.map +1 -1
- package/dist/toast/toast.mjs +5 -1
- package/dist/toast/toast.mjs.map +1 -1
- package/dist/toggle/toggle.mjs +2 -1
- package/dist/toggle/toggle.mjs.map +1 -1
- package/dist/toggle-group/index.d.mts +16 -0
- package/dist/toggle-group/index.d.mts.map +1 -0
- package/dist/toggle-group/index.mjs +15 -0
- package/dist/toggle-group/index.mjs.map +1 -0
- package/dist/toggle-group/toggle-group-context.d.mts +4 -0
- package/dist/toggle-group/toggle-group-context.d.mts.map +1 -0
- package/dist/toggle-group/toggle-group-context.mjs +13 -0
- package/dist/toggle-group/toggle-group-context.mjs.map +1 -0
- package/dist/toggle-group/toggle-group-item.d.mts +47 -0
- package/dist/toggle-group/toggle-group-item.d.mts.map +1 -0
- package/dist/toggle-group/toggle-group-item.mjs +63 -0
- package/dist/toggle-group/toggle-group-item.mjs.map +1 -0
- package/dist/toggle-group/toggle-group-root.d.mts +95 -0
- package/dist/toggle-group/toggle-group-root.d.mts.map +1 -0
- package/dist/toggle-group/toggle-group-root.mjs +211 -0
- package/dist/toggle-group/toggle-group-root.mjs.map +1 -0
- package/dist/toolbar/index.d.mts +18 -0
- package/dist/toolbar/index.d.mts.map +1 -0
- package/dist/toolbar/index.mjs +18 -0
- package/dist/toolbar/index.mjs.map +1 -0
- package/dist/toolbar/toolbar-button.d.mts +42 -0
- package/dist/toolbar/toolbar-button.d.mts.map +1 -0
- package/dist/toolbar/toolbar-button.mjs +50 -0
- package/dist/toolbar/toolbar-button.mjs.map +1 -0
- package/dist/toolbar/toolbar-root.d.mts +38 -0
- package/dist/toolbar/toolbar-root.d.mts.map +1 -0
- package/dist/toolbar/toolbar-root.mjs +66 -0
- package/dist/toolbar/toolbar-root.mjs.map +1 -0
- package/dist/toolbar/toolbar-separator.d.mts +25 -0
- package/dist/toolbar/toolbar-separator.d.mts.map +1 -0
- package/dist/toolbar/toolbar-separator.mjs +31 -0
- package/dist/toolbar/toolbar-separator.mjs.map +1 -0
- package/dist/tooltip/tooltip-popup.mjs +2 -1
- package/dist/tooltip/tooltip-popup.mjs.map +1 -1
- package/dist/tooltip/tooltip-root.mjs +18 -2
- package/dist/tooltip/tooltip-root.mjs.map +1 -1
- package/dist/tooltip/tooltip-trigger.mjs +2 -1
- package/dist/tooltip/tooltip-trigger.mjs.map +1 -1
- package/package.json +6 -1
package/dist/index.d.mts
CHANGED
|
@@ -43,6 +43,14 @@ import { FormSubmitProps, FormSubmitState } from "./form/form-submit.mjs";
|
|
|
43
43
|
import { Form } from "./form/index.mjs";
|
|
44
44
|
import { Toggle, TogglePressedChangeDetails, ToggleProps, ToggleState } from "./toggle/toggle.mjs";
|
|
45
45
|
import "./toggle/index.mjs";
|
|
46
|
+
import { ToggleGroupOrientation } from "./toggle-group/toggle-group-context.mjs";
|
|
47
|
+
import { ToggleGroupItemProps, ToggleGroupItemState } from "./toggle-group/toggle-group-item.mjs";
|
|
48
|
+
import { ToggleGroupExclusiveProps, ToggleGroupMultipleProps, ToggleGroupRootProps, ToggleGroupRootState, ToggleGroupValueChangeDetails } from "./toggle-group/toggle-group-root.mjs";
|
|
49
|
+
import { ToggleGroup } from "./toggle-group/index.mjs";
|
|
50
|
+
import { ToolbarButtonActionDetails, ToolbarButtonProps, ToolbarButtonState } from "./toolbar/toolbar-button.mjs";
|
|
51
|
+
import { ToolbarOrientation, ToolbarRootProps, ToolbarRootState } from "./toolbar/toolbar-root.mjs";
|
|
52
|
+
import { ToolbarSeparatorProps, ToolbarSeparatorState } from "./toolbar/toolbar-separator.mjs";
|
|
53
|
+
import { Toolbar } from "./toolbar/index.mjs";
|
|
46
54
|
import { TabsActivationMode, TabsOrientation } from "./tabs/tabs-context.mjs";
|
|
47
55
|
import { TabsIndicatorProps, TabsIndicatorState } from "./tabs/tabs-indicator.mjs";
|
|
48
56
|
import { TabsListProps, TabsListState } from "./tabs/tabs-list.mjs";
|
|
@@ -101,4 +109,22 @@ import { SliderLabelProps } from "./slider/slider-label.mjs";
|
|
|
101
109
|
import { SliderThumbProps, SliderThumbState } from "./slider/slider-thumb.mjs";
|
|
102
110
|
import { SliderValueProps, SliderValueState } from "./slider/slider-value.mjs";
|
|
103
111
|
import { Slider } from "./slider/index.mjs";
|
|
104
|
-
|
|
112
|
+
import { NumberFieldRootProps, NumberFieldState, NumberFieldValueChangeDetails } from "./number-field/number-field-root.mjs";
|
|
113
|
+
import { NumberFieldButtonState, NumberFieldDecrementProps, NumberFieldIncrementProps } from "./number-field/number-field-increment.mjs";
|
|
114
|
+
import { NumberFieldInputProps } from "./number-field/number-field-input.mjs";
|
|
115
|
+
import { NumberFieldLabelProps } from "./number-field/number-field-label.mjs";
|
|
116
|
+
import { NumberField } from "./number-field/index.mjs";
|
|
117
|
+
import { ProgressRootProps, ProgressState } from "./progress/progress-root.mjs";
|
|
118
|
+
import { ProgressIndicatorProps } from "./progress/progress-indicator.mjs";
|
|
119
|
+
import { ProgressLabelProps } from "./progress/progress-label.mjs";
|
|
120
|
+
import { ProgressTrackProps } from "./progress/progress-track.mjs";
|
|
121
|
+
import { ProgressValueProps } from "./progress/progress-value.mjs";
|
|
122
|
+
import { Progress } from "./progress/index.mjs";
|
|
123
|
+
import { MeterRegion } from "./meter/meter-region.mjs";
|
|
124
|
+
import { MeterRootProps, MeterState } from "./meter/meter-root.mjs";
|
|
125
|
+
import { MeterIndicatorProps } from "./meter/meter-indicator.mjs";
|
|
126
|
+
import { MeterLabelProps } from "./meter/meter-label.mjs";
|
|
127
|
+
import { MeterTrackProps } from "./meter/meter-track.mjs";
|
|
128
|
+
import { MeterValueProps } from "./meter/meter-value.mjs";
|
|
129
|
+
import { Meter } from "./meter/index.mjs";
|
|
130
|
+
export { Accordion, type AccordionItemProps, type AccordionItemState, type AccordionPanelProps, type AccordionPanelState, type AccordionRootExclusiveProps, type AccordionRootMultipleProps, type AccordionRootProps, type AccordionRootState, type AccordionTriggerProps, type AccordionTriggerState, type AccordionValueChangeDetails, type Action, type ActionDetails, type ChangeAction, type ChangeReason, Checkbox, type CheckboxCheckedChangeDetails, CheckboxGroup, type CheckboxGroupItemProps, type CheckboxGroupItemState, type CheckboxGroupLabelProps, type CheckboxGroupParentProps, type CheckboxGroupParentState, type CheckboxGroupRootProps, type CheckboxGroupRootState, type CheckboxGroupValueChangeDetails, type CheckboxProps, type CheckboxState, Combobox, type ComboboxClearProps, type ComboboxClearState, type ComboboxEmptyProps, type ComboboxEmptyState, type ComboboxGroupLabelProps, type ComboboxGroupLabelState, type ComboboxGroupProps, type ComboboxGroupState, type ComboboxInputProps, type ComboboxInputState, type ComboboxInputValueChangeDetails, type ComboboxLabelProps, type ComboboxLabelState, type ComboboxListProps, type ComboboxListState, type ComboboxOpenChangeDetails, type ComboboxOptionProps, type ComboboxOptionState, type ComboboxPopupProps, type ComboboxPopupState, type ComboboxRootProps, type ComboboxRootState, type ComboboxStatusProps, type ComboboxStatusState, type ComboboxTriggerProps, type ComboboxTriggerState, type ComboboxValueChangeDetails, Dialog, type DialogCloseDetails, type DialogCloseProps, type DialogCloseState, type DialogDescriptionProps, type DialogDescriptionState, type DialogFormProps, type DialogFormState, type DialogOpenChangeDetails, type DialogPopupProps, type DialogPopupState, type DialogRootProps, type DialogRootState, type DialogTitleProps, type DialogTitleState, type DialogTriggerProps, type DialogTriggerState, Field, type FieldControlProps, type FieldDescriptionProps, type FieldErrorProps, type FieldErrorValue, type FieldLabelProps, type FieldRootProps, type FieldState, type FieldValidate, type FieldValidity, Form, type FormErrors, type FormRootProps, type FormRootState, type FormSubmitProps, type FormSubmitState, Menu, type MenuAlign, type MenuCheckboxItemProps, type MenuCheckboxItemState, type MenuGroupLabelProps, type MenuGroupLabelState, type MenuGroupProps, type MenuGroupState, type MenuItemDetails, type MenuItemProps, type MenuItemState, type MenuOpenChangeDetails, type MenuPopupProps, type MenuPopupState, type MenuRadioGroupProps, type MenuRadioGroupState, type MenuRadioItemProps, type MenuRadioItemState, type MenuRootProps, type MenuRootState, type MenuSeparatorProps, type MenuSeparatorState, type MenuSide, type MenuSubmenuTriggerProps, type MenuSubmenuTriggerState, type MenuTriggerProps, type MenuTriggerState, Meter, type MeterIndicatorProps, type MeterLabelProps, type MeterRegion, type MeterRootProps, type MeterState, type MeterTrackProps, type MeterValueProps, NumberField, type NumberFieldButtonState, type NumberFieldDecrementProps, type NumberFieldIncrementProps, type NumberFieldInputProps, type NumberFieldLabelProps, type NumberFieldRootProps, type NumberFieldState, type NumberFieldValueChangeDetails, Popover, type PopoverAlign, type PopoverCloseProps, type PopoverCloseState, type PopoverDescriptionProps, type PopoverDescriptionState, type PopoverOpenChangeDetails, type PopoverPopupProps, type PopoverPopupState, type PopoverRootProps, type PopoverRootState, type PopoverSide, type PopoverTitleProps, type PopoverTitleState, type PopoverTriggerProps, type PopoverTriggerState, Progress, type ProgressIndicatorProps, type ProgressLabelProps, type ProgressRootProps, type ProgressState, type ProgressTrackProps, type ProgressValueProps, RadioGroup, type RadioGroupItemProps, type RadioGroupItemState, type RadioGroupLabelProps, type RadioGroupRootProps, type RadioGroupRootState, type RadioGroupValueChangeDetails, type RenderProp, Select, type SelectGroupLabelProps, type SelectGroupProps, type SelectOptionProps, type SelectOptionState, type SelectRootProps, type SelectRootState, type SelectSeparatorProps, type SelectTriggerProps, type SelectValueChangeDetails, type SelectValueProps, Slider, type SliderIndicatorProps, type SliderIndicatorState, type SliderLabelProps, type SliderOrientation, type SliderRootProps, type SliderRootState, type SliderThumbProps, type SliderThumbState, type SliderTrackProps, type SliderTrackState, type SliderValue, type SliderValueChangeDetails, type SliderValueCommitDetails, type SliderValueProps, type SliderValueState, type StateValue, Switch, type SwitchCheckedChangeDetails, type SwitchProps, type SwitchState, Tabs, type TabsActivationMode, type TabsIndicatorProps, type TabsIndicatorState, type TabsListProps, type TabsListState, type TabsOrientation, type TabsPanelProps, type TabsPanelState, type TabsRootProps, type TabsRootState, type TabsTabProps, type TabsTabState, type TabsValueChangeDetails, Toast, type ToastActionDetails, type ToastActionOptions, type ToastActionProps, type ToastActionState, type ToastCloseDetails, type ToastCloseProps, type ToastCloseState, type ToastDescriptionProps, type ToastItem, type ToastManager, type ToastOptions, type ToastPriority, type ToastPromiseOptions, type ToastRootProps, type ToastRootState, type ToastTitleProps, type ToastViewportProps, type ToastViewportState, Toggle, ToggleGroup, type ToggleGroupExclusiveProps, type ToggleGroupItemProps, type ToggleGroupItemState, type ToggleGroupMultipleProps, type ToggleGroupOrientation, type ToggleGroupRootProps, type ToggleGroupRootState, type ToggleGroupValueChangeDetails, type TogglePressedChangeDetails, type ToggleProps, type ToggleState, Toolbar, type ToolbarButtonActionDetails, type ToolbarButtonProps, type ToolbarButtonState, type ToolbarOrientation, type ToolbarRootProps, type ToolbarRootState, type ToolbarSeparatorProps, type ToolbarSeparatorState, Tooltip, type TooltipAlign, type TooltipPopupProps, type TooltipPopupState, type TooltipProvides, type TooltipRootProps, type TooltipRootState, type TooltipSide, type TooltipTriggerProps, type TooltipTriggerState, type UrgentChangeAction, createToastManager, toast };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Toggle } from "./toggle/toggle.mjs";
|
|
2
|
+
import { ToggleGroup } from "./toggle-group/index.mjs";
|
|
3
|
+
import { Toolbar } from "./toolbar/index.mjs";
|
|
2
4
|
import { Accordion } from "./accordion/index.mjs";
|
|
3
5
|
import { Tabs } from "./tabs/index.mjs";
|
|
4
6
|
import { Tooltip } from "./tooltip/index.mjs";
|
|
@@ -14,6 +16,9 @@ import { Combobox } from "./combobox/index.mjs";
|
|
|
14
16
|
import { createToastManager, toast } from "./toast/toast.mjs";
|
|
15
17
|
import { Toast } from "./toast/index.mjs";
|
|
16
18
|
import { Slider } from "./slider/index.mjs";
|
|
19
|
+
import { NumberField } from "./number-field/index.mjs";
|
|
17
20
|
import { Field } from "./field/index.mjs";
|
|
18
21
|
import { Form } from "./form/index.mjs";
|
|
19
|
-
|
|
22
|
+
import { Progress } from "./progress/index.mjs";
|
|
23
|
+
import { Meter } from "./meter/index.mjs";
|
|
24
|
+
export { Accordion, Checkbox, CheckboxGroup, Combobox, Dialog, Field, Form, Menu, Meter, NumberField, Popover, Progress, RadioGroup, Select, Slider, Switch, Tabs, Toast, Toggle, ToggleGroup, Toolbar, Tooltip, createToastManager, toast };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
//#region src/internal/announce.ts
|
|
3
|
+
/** How long the fallback region keeps a message before it is cleared, so a repeat is spoken. */
|
|
4
|
+
const ANNOUNCE_CLEAR_DELAY = 1e3;
|
|
5
|
+
const REGION_STYLE = "position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;";
|
|
6
|
+
let region = null;
|
|
7
|
+
let clearTimer;
|
|
8
|
+
let writeTimer;
|
|
9
|
+
function liveRegion(doc) {
|
|
10
|
+
if (region !== null && region.isConnected && region.ownerDocument === doc) return region;
|
|
11
|
+
const el = doc.createElement("div");
|
|
12
|
+
el.setAttribute("role", "status");
|
|
13
|
+
el.setAttribute("aria-live", "polite");
|
|
14
|
+
el.setAttribute("aria-atomic", "true");
|
|
15
|
+
el.setAttribute("data-fsui-announcer", "");
|
|
16
|
+
el.setAttribute("style", REGION_STYLE);
|
|
17
|
+
doc.body.append(el);
|
|
18
|
+
region = el;
|
|
19
|
+
return el;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Speaks `message` in the context of `element`: `element.ariaNotify(message)` where it exists,
|
|
23
|
+
* else the fallback live region (inserted on first use, cleared, then written
|
|
24
|
+
* `ANNOUNCE_WRITE_DELAY` ms later and cleared again after `ANNOUNCE_CLEAR_DELAY`). An empty
|
|
25
|
+
* message announces nothing; a newer message replaces one not yet written.
|
|
26
|
+
*/
|
|
27
|
+
function announce(element, message) {
|
|
28
|
+
if (message === "") return;
|
|
29
|
+
const notifying = element;
|
|
30
|
+
if (typeof notifying.ariaNotify === "function") {
|
|
31
|
+
notifying.ariaNotify(message);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const doc = element.ownerDocument;
|
|
35
|
+
if (doc.body === null) return;
|
|
36
|
+
const el = liveRegion(doc);
|
|
37
|
+
el.textContent = "";
|
|
38
|
+
if (clearTimer !== void 0) clearTimeout(clearTimer);
|
|
39
|
+
if (writeTimer !== void 0) clearTimeout(writeTimer);
|
|
40
|
+
clearTimer = void 0;
|
|
41
|
+
writeTimer = setTimeout(() => {
|
|
42
|
+
writeTimer = void 0;
|
|
43
|
+
el.textContent = message;
|
|
44
|
+
clearTimer = setTimeout(() => {
|
|
45
|
+
clearTimer = void 0;
|
|
46
|
+
el.textContent = "";
|
|
47
|
+
}, ANNOUNCE_CLEAR_DELAY);
|
|
48
|
+
}, 100);
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { ANNOUNCE_CLEAR_DELAY, announce };
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=announce.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"announce.mjs","names":[],"sources":["../../src/internal/announce.ts"],"sourcesContent":["\"use client\";\n// Screen-reader announcements (design/components/number-field.md 8.3, conventions 8): through\n// `ariaNotify()` where the engine has it, otherwise through one module-level, visually hidden\n// `role=\"status\"` live region appended to `document.body` on first use. No part renders a live\n// region of its own for these announcements.\n\ntype NotifyingElement = Element & { ariaNotify?: (announcement: string) => void };\n\n/** How long the fallback region keeps a message before it is cleared, so a repeat is spoken. */\nexport const ANNOUNCE_CLEAR_DELAY = 1000;\n\nconst REGION_STYLE =\n \"position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; \" +\n \"overflow: hidden; clip-path: inset(50%); white-space: nowrap;\";\n\n/**\n * The delay between clearing the region and writing a message. A region inserted in the same task\n * as its first message is skipped by some screen readers, and an unchanged text is not spoken\n * again; clearing first and writing a tick later makes every message a fresh change.\n */\nexport const ANNOUNCE_WRITE_DELAY = 100;\n\nlet region: HTMLElement | null = null;\nlet clearTimer: ReturnType<typeof setTimeout> | undefined;\nlet writeTimer: ReturnType<typeof setTimeout> | undefined;\n\nfunction liveRegion(doc: Document): HTMLElement {\n if (region !== null && region.isConnected && region.ownerDocument === doc) return region;\n const el = doc.createElement(\"div\");\n el.setAttribute(\"role\", \"status\");\n el.setAttribute(\"aria-live\", \"polite\");\n el.setAttribute(\"aria-atomic\", \"true\");\n el.setAttribute(\"data-fsui-announcer\", \"\");\n el.setAttribute(\"style\", REGION_STYLE);\n doc.body.append(el);\n region = el;\n return el;\n}\n\n/**\n * Speaks `message` in the context of `element`: `element.ariaNotify(message)` where it exists,\n * else the fallback live region (inserted on first use, cleared, then written\n * `ANNOUNCE_WRITE_DELAY` ms later and cleared again after `ANNOUNCE_CLEAR_DELAY`). An empty\n * message announces nothing; a newer message replaces one not yet written.\n */\nexport function announce(element: Element, message: string): void {\n if (message === \"\") return;\n const notifying = element as NotifyingElement;\n if (typeof notifying.ariaNotify === \"function\") {\n notifying.ariaNotify(message);\n return;\n }\n const doc = element.ownerDocument;\n if (doc.body === null) return;\n const el = liveRegion(doc);\n el.textContent = \"\";\n if (clearTimer !== undefined) clearTimeout(clearTimer);\n if (writeTimer !== undefined) clearTimeout(writeTimer);\n clearTimer = undefined;\n writeTimer = setTimeout(() => {\n writeTimer = undefined;\n el.textContent = message;\n clearTimer = setTimeout(() => {\n clearTimer = undefined;\n el.textContent = \"\";\n }, ANNOUNCE_CLEAR_DELAY);\n }, ANNOUNCE_WRITE_DELAY);\n}\n"],"mappings":";;;AASA,MAAa,uBAAuB;AAEpC,MAAM,eACJ;AAUF,IAAI,SAA6B;AACjC,IAAI;AACJ,IAAI;AAEJ,SAAS,WAAW,KAA4B;CAC9C,IAAI,WAAW,QAAQ,OAAO,eAAe,OAAO,kBAAkB,KAAK,OAAO;CAClF,MAAM,KAAK,IAAI,cAAc,KAAK;CAClC,GAAG,aAAa,QAAQ,QAAQ;CAChC,GAAG,aAAa,aAAa,QAAQ;CACrC,GAAG,aAAa,eAAe,MAAM;CACrC,GAAG,aAAa,uBAAuB,EAAE;CACzC,GAAG,aAAa,SAAS,YAAY;CACrC,IAAI,KAAK,OAAO,EAAE;CAClB,SAAS;CACT,OAAO;AACT;;;;;;;AAQA,SAAgB,SAAS,SAAkB,SAAuB;CAChE,IAAI,YAAY,IAAI;CACpB,MAAM,YAAY;CAClB,IAAI,OAAO,UAAU,eAAe,YAAY;EAC9C,UAAU,WAAW,OAAO;EAC5B;CACF;CACA,MAAM,MAAM,QAAQ;CACpB,IAAI,IAAI,SAAS,MAAM;CACvB,MAAM,KAAK,WAAW,GAAG;CACzB,GAAG,cAAc;CACjB,IAAI,eAAe,KAAA,GAAW,aAAa,UAAU;CACrD,IAAI,eAAe,KAAA,GAAW,aAAa,UAAU;CACrD,aAAa,KAAA;CACb,aAAa,iBAAiB;EAC5B,aAAa,KAAA;EACb,GAAG,cAAc;EACjB,aAAa,iBAAiB;GAC5B,aAAa,KAAA;GACb,GAAG,cAAc;EACnB,GAAG,oBAAoB;CACzB,GAAA,GAAuB;AACzB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/internal/decimal.ts
|
|
2
|
+
/** Number of decimal places of `n` as written (`0.1` → 1, `1e-7` → 7, `5` → 0). */
|
|
3
|
+
function decimalsOf(n) {
|
|
4
|
+
if (!Number.isFinite(n)) return 0;
|
|
5
|
+
const text = String(n);
|
|
6
|
+
const exponent = /e-(\d+)$/i.exec(text);
|
|
7
|
+
if (exponent !== null) {
|
|
8
|
+
const mantissa = text.slice(0, exponent.index);
|
|
9
|
+
const dot = mantissa.indexOf(".");
|
|
10
|
+
return Number(exponent[1]) + (dot === -1 ? 0 : mantissa.length - dot - 1);
|
|
11
|
+
}
|
|
12
|
+
const dot = text.indexOf(".");
|
|
13
|
+
return dot === -1 ? 0 : text.length - dot - 1;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* `value` rounded to `decimals` places through `toFixed` (decimal, not binary, rounding of the
|
|
17
|
+
* written digits: `roundTo(0.1 + 0.2, 1)` is `0.3`). `-0` becomes `0`.
|
|
18
|
+
*/
|
|
19
|
+
function roundTo(value, decimals) {
|
|
20
|
+
if (!Number.isFinite(value)) return value;
|
|
21
|
+
const result = decimals <= 0 ? Math.round(value) : Number(value.toFixed(Math.min(decimals, 100)));
|
|
22
|
+
return result === 0 ? 0 : result;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { decimalsOf, roundTo };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=decimal.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decimal.mjs","names":[],"sources":["../../src/internal/decimal.ts"],"sourcesContent":["// Decimal helpers shared by Slider and NumberField (design/components/number-field.md 5.4). No\n// directive: no React, no client-only API.\n\n/** Number of decimal places of `n` as written (`0.1` → 1, `1e-7` → 7, `5` → 0). */\nexport function decimalsOf(n: number): number {\n if (!Number.isFinite(n)) return 0;\n const text = String(n);\n const exponent = /e-(\\d+)$/i.exec(text);\n if (exponent !== null) {\n const mantissa = text.slice(0, exponent.index);\n const dot = mantissa.indexOf(\".\");\n return Number(exponent[1]) + (dot === -1 ? 0 : mantissa.length - dot - 1);\n }\n const dot = text.indexOf(\".\");\n return dot === -1 ? 0 : text.length - dot - 1;\n}\n\n/**\n * `value` rounded to `decimals` places through `toFixed` (decimal, not binary, rounding of the\n * written digits: `roundTo(0.1 + 0.2, 1)` is `0.3`). `-0` becomes `0`.\n */\nexport function roundTo(value: number, decimals: number): number {\n if (!Number.isFinite(value)) return value;\n // `toFixed` takes at most 100 digits; anything near that is already exact.\n const result = decimals <= 0 ? Math.round(value) : Number(value.toFixed(Math.min(decimals, 100)));\n return result === 0 ? 0 : result;\n}\n"],"mappings":";;AAIA,SAAgB,WAAW,GAAmB;CAC5C,IAAI,CAAC,OAAO,SAAS,CAAC,GAAG,OAAO;CAChC,MAAM,OAAO,OAAO,CAAC;CACrB,MAAM,WAAW,YAAY,KAAK,IAAI;CACtC,IAAI,aAAa,MAAM;EACrB,MAAM,WAAW,KAAK,MAAM,GAAG,SAAS,KAAK;EAC7C,MAAM,MAAM,SAAS,QAAQ,GAAG;EAChC,OAAO,OAAO,SAAS,EAAE,KAAK,QAAQ,KAAK,IAAI,SAAS,SAAS,MAAM;CACzE;CACA,MAAM,MAAM,KAAK,QAAQ,GAAG;CAC5B,OAAO,QAAQ,KAAK,IAAI,KAAK,SAAS,MAAM;AAC9C;;;;;AAMA,SAAgB,QAAQ,OAAe,UAA0B;CAC/D,IAAI,CAAC,OAAO,SAAS,KAAK,GAAG,OAAO;CAEpC,MAAM,SAAS,YAAY,IAAI,KAAK,MAAM,KAAK,IAAI,OAAO,MAAM,QAAQ,KAAK,IAAI,UAAU,GAAG,CAAC,CAAC;CAChG,OAAO,WAAW,IAAI,IAAI;AAC5B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/internal/dev-warn.ts
|
|
2
|
+
const isDev = process.env.NODE_ENV !== "production";
|
|
3
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4
|
+
/**
|
|
5
|
+
* Logs `message` through `console.error` once per `key` in development. Called during render,
|
|
6
|
+
* so a discarded render may warn; keys name the part and the condition (a Server Component has
|
|
7
|
+
* no element identity to key on).
|
|
8
|
+
*/
|
|
9
|
+
function warnOnce(key, message) {
|
|
10
|
+
if (!isDev || seen.has(key)) return;
|
|
11
|
+
seen.add(key);
|
|
12
|
+
console.error(message);
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { warnOnce };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=dev-warn.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-warn.mjs","names":[],"sources":["../../src/internal/dev-warn.ts"],"sourcesContent":["// No \"use client\": usable during the render of a directive-free part that may run as a Server\n// Component, where an effect (`useDevWarning`) never runs (design/components/progress.md 8.1,\n// implementation note 14.3).\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\nconst seen = new Set<string>();\n\n/**\n * Logs `message` through `console.error` once per `key` in development. Called during render,\n * so a discarded render may warn; keys name the part and the condition (a Server Component has\n * no element identity to key on).\n */\nexport function warnOnce(key: string, message: string): void {\n if (!isDev || seen.has(key)) return;\n seen.add(key);\n console.error(message);\n}\n\n/** Tests only: forget every key, so the next `warnOnce` warns again. */\nexport function resetWarnOnce(): void {\n seen.clear();\n}\n"],"mappings":";AAIA,MAAM,QAAQ,QAAQ,IAAI,aAAa;AAEvC,MAAM,uBAAO,IAAI,IAAY;;;;;;AAO7B,SAAgB,SAAS,KAAa,SAAuB;CAC3D,IAAI,CAAC,SAAS,KAAK,IAAI,GAAG,GAAG;CAC7B,KAAK,IAAI,GAAG;CACZ,QAAQ,MAAM,OAAO;AACvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-context.mjs","names":[],"sources":["../../src/internal/field-context.ts"],"sourcesContent":["\"use client\";\nimport { createContext, use } from \"react\";\nimport type { FieldValidity, FormErrors } from \"./validity.js\";\n\n/** The state every Field part receives (design/components/field-form.md 4.1). */\nexport interface FieldState {\n /** An error is shown: the control matches `:user-invalid`, or a server error for this field is shown. */\n readonly invalid: boolean;\n /** The messages shown: `[validationMessage]` for a native constraint, the strings `validate` returned for a custom one, the server's strings for a server error; `[]` while valid. */\n readonly messages: readonly string[];\n /** A snapshot of the control's `ValidityState` (all valid on the server and before the first read). */\n readonly validity: FieldValidity;\n /** `Field.Root disabled` or the control's own `disabled`. */\n readonly disabled: boolean;\n /** `Field.Root required` or the control's own `required`. */\n readonly required: boolean;\n /** The enclosing form's submission is in flight (`useFormStatus().pending`); `false` outside a form. */\n readonly pending: boolean;\n}\n\nexport interface FieldIds {\n readonly control: string;\n readonly label: string;\n readonly description: string;\n readonly error: string;\n}\n\n/** What a control reports to its Field (design 7.1). */\nexport interface FieldControlRegistration {\n /** The element the Field labels, describes and listens to (the input, or a group's fieldset). */\n readonly element: HTMLElement;\n /** `<label for>` can target it. Groups report `false`. */\n readonly labelable: boolean;\n /** The control's own `required` / `disabled` props (for the Field's `data-*` state). */\n readonly required: boolean;\n readonly disabled: boolean;\n}\n\nexport interface FieldContextValue {\n readonly ids: FieldIds;\n /** `Field.Root name`. */\n readonly name: string | undefined;\n /** `Field.Root disabled` / `required` (the props, not the merged state). */\n readonly disabled: boolean;\n readonly required: boolean;\n readonly state: FieldState;\n /** The registered control is labelable (default `true`, also before any registration). */\n readonly labelable: boolean;\n /** Registers the Field's control; returns the unregister function. The first one wins. */\n readonly registerControl: (registration: FieldControlRegistration) => () => void;\n /** A `Field.Error` is mounted (the Field may cancel the platform bubble). */\n readonly registerError: () => () => void;\n /**\n * The control's value changed in the DOM without an `input` / `change` event the Field could\n * hear (a Combobox selection, a CheckboxGroup's derived `required`, a rolled-back optimistic\n * value): re-reads the slot and the mirror after the commit that wrote it, and refreshes the\n * other Fields of the `Form.Root` (cross-field rules). `edit`: the user made the change, so a\n * shown server error is dismissed as by an `input` event. Call from a layout effect.\n */\n readonly notifyChange: (edit: boolean) => void;\n}\n\nexport const FieldContext = createContext<FieldContextValue | null>(null);\n\nexport function useFieldContext(part: string): FieldContextValue {\n const ctx = use(FieldContext);\n if (ctx === null) throw new Error(`${part} must be rendered inside a Field.Root.`);\n return ctx;\n}\n\n/** What a Field registers with its Form (design 3.5). */\nexport interface FormFieldRegistration {\n /** The control, or a group's first enabled (or checked) member. */\n readonly getFocusTarget: () => HTMLElement | null;\n /** The Field shows a server error at the latest commit. */\n readonly showsServerError: () => boolean;\n /** The server messages shown, for an announcement when focus does not move. */\n readonly serverMessages: () => readonly string[];\n /** Re-runs `validate` and re-reads validity (another Field's control changed). */\n readonly refresh: () => void;\n}\n\nexport interface FormContextValue {\n readonly errors: FormErrors | undefined;\n readonly registerField: (registration: FormFieldRegistration) => () => void;\n /**\n * The `FormData` of the submission in flight when the Form ran it itself (the intercepted path),\n * else `null`: the stale-value suppression of design 3.2 item 2 is computed against it.\n */\n readonly submittedData: () => FormData | null;\n /** Refreshes every registered Field except `source` (a change no DOM event carried). */\n readonly refreshFields: (source: FormFieldRegistration | null) => void;\n}\n\nexport const FormContext = createContext<FormContextValue | null>(null);\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"field-context.mjs","names":[],"sources":["../../src/internal/field-context.ts"],"sourcesContent":["\"use client\";\nimport { createContext, use } from \"react\";\nimport type { FieldValidity, FormErrors, ValidatableElement } from \"./validity.js\";\n\n/** The state every Field part receives (design/components/field-form.md 4.1). */\nexport interface FieldState {\n /** An error is shown: the control matches `:user-invalid`, or a server error for this field is shown. */\n readonly invalid: boolean;\n /** The messages shown: `[validationMessage]` for a native constraint, the strings `validate` returned for a custom one, the server's strings for a server error; `[]` while valid. */\n readonly messages: readonly string[];\n /** A snapshot of the control's `ValidityState` (all valid on the server and before the first read). */\n readonly validity: FieldValidity;\n /** `Field.Root disabled` or the control's own `disabled`. */\n readonly disabled: boolean;\n /** `Field.Root required` or the control's own `required`. */\n readonly required: boolean;\n /** The enclosing form's submission is in flight (`useFormStatus().pending`); `false` outside a form. */\n readonly pending: boolean;\n}\n\nexport interface FieldIds {\n readonly control: string;\n readonly label: string;\n readonly description: string;\n readonly error: string;\n}\n\n/** What a control reports to its Field (design 7.1). */\nexport interface FieldControlRegistration {\n /** The element the Field labels, describes and listens to (the input, or a group's fieldset). */\n readonly element: HTMLElement;\n /** `<label for>` can target it. Groups report `false`. */\n readonly labelable: boolean;\n /** The control's own `required` / `disabled` props (for the Field's `data-*` state). */\n readonly required: boolean;\n readonly disabled: boolean;\n /**\n * Where `validity`, `validationMessage` and the custom-validity slot are read and written when\n * that is not the registered element (NumberField: the hidden `input[type=number]` after the\n * visible text input). `:user-invalid`, the listeners and the focus target stay on `element`;\n * after writing the slot the Field mirrors this element's `validationMessage` into `element`\n * (design/components/field-form.md, amendment `validityElement`). Resolved on every read.\n */\n readonly validityElement?: (() => ValidatableElement | null) | undefined;\n}\n\nexport interface FieldContextValue {\n readonly ids: FieldIds;\n /** `Field.Root name`. */\n readonly name: string | undefined;\n /** `Field.Root disabled` / `required` (the props, not the merged state). */\n readonly disabled: boolean;\n readonly required: boolean;\n readonly state: FieldState;\n /** The registered control is labelable (default `true`, also before any registration). */\n readonly labelable: boolean;\n /** Registers the Field's control; returns the unregister function. The first one wins. */\n readonly registerControl: (registration: FieldControlRegistration) => () => void;\n /** A `Field.Error` is mounted (the Field may cancel the platform bubble). */\n readonly registerError: () => () => void;\n /**\n * The control's value changed in the DOM without an `input` / `change` event the Field could\n * hear (a Combobox selection, a CheckboxGroup's derived `required`, a rolled-back optimistic\n * value): re-reads the slot and the mirror after the commit that wrote it, and refreshes the\n * other Fields of the `Form.Root` (cross-field rules). `edit`: the user made the change, so a\n * shown server error is dismissed as by an `input` event. Call from a layout effect.\n */\n readonly notifyChange: (edit: boolean) => void;\n}\n\nexport const FieldContext = createContext<FieldContextValue | null>(null);\n\nexport function useFieldContext(part: string): FieldContextValue {\n const ctx = use(FieldContext);\n if (ctx === null) throw new Error(`${part} must be rendered inside a Field.Root.`);\n return ctx;\n}\n\n/** What a Field registers with its Form (design 3.5). */\nexport interface FormFieldRegistration {\n /** The control, or a group's first enabled (or checked) member. */\n readonly getFocusTarget: () => HTMLElement | null;\n /** The Field shows a server error at the latest commit. */\n readonly showsServerError: () => boolean;\n /** The server messages shown, for an announcement when focus does not move. */\n readonly serverMessages: () => readonly string[];\n /** Re-runs `validate` and re-reads validity (another Field's control changed). */\n readonly refresh: () => void;\n}\n\nexport interface FormContextValue {\n readonly errors: FormErrors | undefined;\n readonly registerField: (registration: FormFieldRegistration) => () => void;\n /**\n * The `FormData` of the submission in flight when the Form ran it itself (the intercepted path),\n * else `null`: the stale-value suppression of design 3.2 item 2 is computed against it.\n */\n readonly submittedData: () => FormData | null;\n /** Refreshes every registered Field except `source` (a change no DOM event carried). */\n readonly refreshFields: (source: FormFieldRegistration | null) => void;\n}\n\nexport const FormContext = createContext<FormContextValue | null>(null);\n"],"mappings":";;;AAsEA,MAAa,eAAe,cAAwC,IAAI;AAExE,SAAgB,gBAAgB,MAAiC;CAC/D,MAAM,MAAM,IAAI,YAAY;CAC5B,IAAI,QAAQ,MAAM,MAAM,IAAI,MAAM,GAAG,KAAK,uCAAuC;CACjF,OAAO;AACT;AA0BA,MAAa,cAAc,cAAuC,IAAI"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/internal/range-value.ts
|
|
2
|
+
/** The platform's clamp (`<progress>` 150 of 100 is 100). A degenerate range yields `min`. */
|
|
3
|
+
function clamp(value, min, max) {
|
|
4
|
+
return Math.max(min, Math.min(max, value));
|
|
5
|
+
}
|
|
6
|
+
/** Whether `[min, max]` is empty or a point (`max <= min`): a bug at the call site. */
|
|
7
|
+
function isDegenerate(min, max) {
|
|
8
|
+
return !(max > min);
|
|
9
|
+
}
|
|
10
|
+
/** `(value - min) / (max - min)`, `0` for a degenerate range. */
|
|
11
|
+
function fraction(value, min, max) {
|
|
12
|
+
return isDegenerate(min, max) ? 0 : (value - min) / (max - min);
|
|
13
|
+
}
|
|
14
|
+
/** The fraction as a number 0–100. */
|
|
15
|
+
function percentage(value, min, max) {
|
|
16
|
+
return fraction(value, min, max) * 100;
|
|
17
|
+
}
|
|
18
|
+
const PERCENT = { style: "percent" };
|
|
19
|
+
const CACHE_LIMIT = 32;
|
|
20
|
+
const formatters = /* @__PURE__ */ new Map();
|
|
21
|
+
/**
|
|
22
|
+
* One `Intl.NumberFormat` per `locale` + `format`, so an update loop does not construct one per
|
|
23
|
+
* render. Bounded: past 32 entries the oldest is dropped.
|
|
24
|
+
*/
|
|
25
|
+
function getNumberFormat(locale, format) {
|
|
26
|
+
const options = format ?? PERCENT;
|
|
27
|
+
const key = `${locale ?? ""}\u0000${JSON.stringify(options)}`;
|
|
28
|
+
let formatter = formatters.get(key);
|
|
29
|
+
if (formatter === void 0) {
|
|
30
|
+
formatter = new Intl.NumberFormat(locale, options);
|
|
31
|
+
if (formatters.size >= CACHE_LIMIT) {
|
|
32
|
+
const oldest = formatters.keys().next().value;
|
|
33
|
+
if (oldest !== void 0) formatters.delete(oldest);
|
|
34
|
+
}
|
|
35
|
+
formatters.set(key, formatter);
|
|
36
|
+
}
|
|
37
|
+
return formatter;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The visible text of a (clamped) value: the fraction of the range for the `percent` style (the
|
|
41
|
+
* default when `format` is absent), the value itself for any other style. A `format` without
|
|
42
|
+
* `style` is `decimal` per `Intl` and formats the value.
|
|
43
|
+
*/
|
|
44
|
+
function formatRangeValue(value, min, max, format, locale) {
|
|
45
|
+
const percentStyle = format === void 0 || format.style === "percent";
|
|
46
|
+
return getNumberFormat(locale, format).format(percentStyle ? fraction(value, min, max) : value);
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { clamp, formatRangeValue, fraction, getNumberFormat, isDegenerate, percentage };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=range-value.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"range-value.mjs","names":[],"sources":["../../src/internal/range-value.ts"],"sourcesContent":["// No \"use client\": pure arithmetic and formatting shared by the directive-free `Progress.Root`\n// and `Meter.Root` (design/components/progress.md 2.1, 2.2 and implementation note 14.4).\n\n/** The platform's clamp (`<progress>` 150 of 100 is 100). A degenerate range yields `min`. */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\n/** Whether `[min, max]` is empty or a point (`max <= min`): a bug at the call site. */\nexport function isDegenerate(min: number, max: number): boolean {\n return !(max > min);\n}\n\n/** `(value - min) / (max - min)`, `0` for a degenerate range. */\nexport function fraction(value: number, min: number, max: number): number {\n return isDegenerate(min, max) ? 0 : (value - min) / (max - min);\n}\n\n/** The fraction as a number 0–100. */\nexport function percentage(value: number, min: number, max: number): number {\n return fraction(value, min, max) * 100;\n}\n\nconst PERCENT: Intl.NumberFormatOptions = { style: \"percent\" };\nconst CACHE_LIMIT = 32;\nconst formatters = new Map<string, Intl.NumberFormat>();\n\n/**\n * One `Intl.NumberFormat` per `locale` + `format`, so an update loop does not construct one per\n * render. Bounded: past 32 entries the oldest is dropped.\n */\nexport function getNumberFormat(\n locale: string | undefined,\n format: Intl.NumberFormatOptions | undefined,\n): Intl.NumberFormat {\n const options = format ?? PERCENT;\n const key = `${locale ?? \"\"}\\u0000${JSON.stringify(options)}`;\n let formatter = formatters.get(key);\n if (formatter === undefined) {\n formatter = new Intl.NumberFormat(locale, options);\n if (formatters.size >= CACHE_LIMIT) {\n const oldest = formatters.keys().next().value;\n if (oldest !== undefined) formatters.delete(oldest);\n }\n formatters.set(key, formatter);\n }\n return formatter;\n}\n\n/**\n * The visible text of a (clamped) value: the fraction of the range for the `percent` style (the\n * default when `format` is absent), the value itself for any other style. A `format` without\n * `style` is `decimal` per `Intl` and formats the value.\n */\nexport function formatRangeValue(\n value: number,\n min: number,\n max: number,\n format: Intl.NumberFormatOptions | undefined,\n locale: string | undefined,\n): string {\n const percentStyle = format === undefined || format.style === \"percent\";\n return getNumberFormat(locale, format).format(percentStyle ? fraction(value, min, max) : value);\n}\n"],"mappings":";;AAIA,SAAgB,MAAM,OAAe,KAAa,KAAqB;CACrE,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAC3C;;AAGA,SAAgB,aAAa,KAAa,KAAsB;CAC9D,OAAO,EAAE,MAAM;AACjB;;AAGA,SAAgB,SAAS,OAAe,KAAa,KAAqB;CACxE,OAAO,aAAa,KAAK,GAAG,IAAI,KAAK,QAAQ,QAAQ,MAAM;AAC7D;;AAGA,SAAgB,WAAW,OAAe,KAAa,KAAqB;CAC1E,OAAO,SAAS,OAAO,KAAK,GAAG,IAAI;AACrC;AAEA,MAAM,UAAoC,EAAE,OAAO,UAAU;AAC7D,MAAM,cAAc;AACpB,MAAM,6BAAa,IAAI,IAA+B;;;;;AAMtD,SAAgB,gBACd,QACA,QACmB;CACnB,MAAM,UAAU,UAAU;CAC1B,MAAM,MAAM,GAAG,UAAU,GAAG,QAAQ,KAAK,UAAU,OAAO;CAC1D,IAAI,YAAY,WAAW,IAAI,GAAG;CAClC,IAAI,cAAc,KAAA,GAAW;EAC3B,YAAY,IAAI,KAAK,aAAa,QAAQ,OAAO;EACjD,IAAI,WAAW,QAAQ,aAAa;GAClC,MAAM,SAAS,WAAW,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;GACxC,IAAI,WAAW,KAAA,GAAW,WAAW,OAAO,MAAM;EACpD;EACA,WAAW,IAAI,KAAK,SAAS;CAC/B;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,iBACd,OACA,KACA,KACA,QACA,QACQ;CACR,MAAM,eAAe,WAAW,KAAA,KAAa,OAAO,UAAU;CAC9D,OAAO,gBAAgB,QAAQ,MAAM,CAAC,CAAC,OAAO,eAAe,SAAS,OAAO,KAAK,GAAG,IAAI,KAAK;AAChG"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { mergeProps, mergeRefs } from "./merge-props.mjs";
|
|
2
|
+
import { cloneElement, createElement, isValidElement } from "react";
|
|
3
|
+
//#region src/internal/render-element.ts
|
|
4
|
+
function resolveStateValue(value, state) {
|
|
5
|
+
return typeof value === "function" ? value(state) : value;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Whether a part whose default element is a `<button>` should add `type="button"`: no `render`,
|
|
9
|
+
* a `render` element whose type is the intrinsic `"button"`, or the function form (it receives
|
|
10
|
+
* button props and decides itself what to spread). An element of any other type (an `<a>`, a
|
|
11
|
+
* router `Link`) does not get it: `type` means something else, or nothing, there.
|
|
12
|
+
*/
|
|
13
|
+
function rendersButton(render) {
|
|
14
|
+
if (render === void 0 || typeof render === "function") return true;
|
|
15
|
+
return isValidElement(render) && render.type === "button";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The ref of a part with no library ref, merged from the consumer's `ref` and a `render`
|
|
19
|
+
* element's ref without memoisation (a directive-free part cannot `useMemo`, design
|
|
20
|
+
* progress.md 14.1). A fresh callback ref per render is correct because every merged callback
|
|
21
|
+
* returns a cleanup; a single ref is passed through untouched.
|
|
22
|
+
*/
|
|
23
|
+
function mergeRenderRef(consumerRef, render) {
|
|
24
|
+
const elementRef = isValidElement(render) ? render.props.ref : void 0;
|
|
25
|
+
if (consumerRef != null && elementRef != null) return mergeRefs(consumerRef, elementRef);
|
|
26
|
+
return consumerRef ?? elementRef;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolves `render` and the function-form `className` / `style` / `children` of a part against
|
|
30
|
+
* its state and produces the element (conventions 1.2, 1.3, 1.4). Pure: the caller merges the
|
|
31
|
+
* refs (`useRender` memoises the merge; a directive-free part merges unmemoised).
|
|
32
|
+
*/
|
|
33
|
+
function renderElement(options) {
|
|
34
|
+
const { defaultElement, render, state, className, style, children, props, libraryProps, ref } = options;
|
|
35
|
+
const partProps = {
|
|
36
|
+
...props,
|
|
37
|
+
ref,
|
|
38
|
+
className: resolveStateValue(className, state),
|
|
39
|
+
style: resolveStateValue(style, state),
|
|
40
|
+
children: resolveStateValue(children, state)
|
|
41
|
+
};
|
|
42
|
+
const controlled = libraryProps ?? {};
|
|
43
|
+
if (isValidElement(render)) {
|
|
44
|
+
const { ref: _ignored, ...elementProps } = render.props;
|
|
45
|
+
return cloneElement(render, mergeProps(partProps, elementProps, controlled));
|
|
46
|
+
}
|
|
47
|
+
const resolved = mergeProps(partProps, {}, controlled);
|
|
48
|
+
if (typeof render === "function") return render(resolved, state);
|
|
49
|
+
return createElement(defaultElement, resolved);
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { mergeRenderRef, renderElement, rendersButton, resolveStateValue };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=render-element.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-element.mjs","names":[],"sources":["../../src/internal/render-element.ts"],"sourcesContent":["// No \"use client\": the pure half of `useRender`, usable from a directive-free part (a Root that\n// may run as a Server Component, design/components/progress.md 8.1 and implementation note 14.1).\nimport { cloneElement, createElement, isValidElement } from \"react\";\nimport type { CSSProperties, ReactNode, Ref } from \"react\";\nimport { mergeProps, mergeRefs } from \"./merge-props.js\";\nimport type { RenderProp, StateValue } from \"./types.js\";\n\nexport interface ElementLikeProps {\n className?: string | undefined;\n style?: CSSProperties | undefined;\n children?: ReactNode;\n ref?: Ref<unknown> | undefined;\n}\n\n/** `data-*` attributes are valid JSX but absent from the element prop types. */\nexport type DataAttributes = { [key: `data-${string}`]: string | undefined };\n\nexport interface RenderElementOptions<Props extends ElementLikeProps, State> {\n /** Intrinsic element rendered when `render` is not given. */\n defaultElement: string;\n render: RenderProp<Props, State> | undefined;\n state: State;\n className: StateValue<string | undefined, State> | undefined;\n style: StateValue<CSSProperties | undefined, State> | undefined;\n children: StateValue<ReactNode, State> | undefined;\n /**\n * The part's pass-through props for the element. A `render` element's own props win over\n * these. Their `ref` is replaced by `ref` below.\n */\n props: Omit<Props, \"className\" | \"style\" | \"children\"> & DataAttributes;\n /**\n * Library-controlled attributes the part computes (`role`, `aria-*` state, id wiring, `data-*`\n * state, the library's own event handlers). These win over a `render` element's props\n * (conventions 1.2).\n */\n libraryProps?: Partial<Omit<Props, \"className\" | \"style\" | \"children\">> & DataAttributes;\n /**\n * The element's ref, already merged from the library's ref, the consumer's `ref` and the\n * `render` element's ref. The `render` element's own ref is not attached separately.\n */\n ref: Ref<unknown> | undefined;\n}\n\nexport function resolveStateValue<T, State>(value: StateValue<T, State>, state: State): T {\n return typeof value === \"function\" ? (value as (state: State) => T)(state) : value;\n}\n\n/**\n * Whether a part whose default element is a `<button>` should add `type=\"button\"`: no `render`,\n * a `render` element whose type is the intrinsic `\"button\"`, or the function form (it receives\n * button props and decides itself what to spread). An element of any other type (an `<a>`, a\n * router `Link`) does not get it: `type` means something else, or nothing, there.\n */\nexport function rendersButton<Props, State>(render: RenderProp<Props, State> | undefined): boolean {\n if (render === undefined || typeof render === \"function\") return true;\n return isValidElement(render) && render.type === \"button\";\n}\n\n/**\n * The ref of a part with no library ref, merged from the consumer's `ref` and a `render`\n * element's ref without memoisation (a directive-free part cannot `useMemo`, design\n * progress.md 14.1). A fresh callback ref per render is correct because every merged callback\n * returns a cleanup; a single ref is passed through untouched.\n */\nexport function mergeRenderRef(\n consumerRef: Ref<unknown> | undefined,\n render: unknown,\n): Ref<unknown> | undefined {\n const elementRef = isValidElement<ElementLikeProps>(render) ? render.props.ref : undefined;\n if (consumerRef != null && elementRef != null) return mergeRefs(consumerRef, elementRef);\n return consumerRef ?? elementRef;\n}\n\n/**\n * Resolves `render` and the function-form `className` / `style` / `children` of a part against\n * its state and produces the element (conventions 1.2, 1.3, 1.4). Pure: the caller merges the\n * refs (`useRender` memoises the merge; a directive-free part merges unmemoised).\n */\nexport function renderElement<Props extends ElementLikeProps, State>(\n options: RenderElementOptions<Props, State>,\n): ReactNode {\n const { defaultElement, render, state, className, style, children, props, libraryProps, ref } =\n options;\n\n const partProps = {\n ...props,\n ref,\n className: resolveStateValue(className, state),\n style: resolveStateValue(style, state),\n children: resolveStateValue(children, state),\n } as Record<string, unknown>;\n const controlled = (libraryProps ?? {}) as Record<string, unknown>;\n\n if (isValidElement<ElementLikeProps>(render)) {\n // The element's ref is already part of `ref`.\n const { ref: _ignored, ...elementProps } = render.props as Record<string, unknown>;\n return cloneElement(render, mergeProps(partProps, elementProps, controlled) as Partial<Props>);\n }\n const resolved = mergeProps(partProps, {}, controlled) as unknown as Props;\n if (typeof render === \"function\") {\n return render(resolved, state);\n }\n return createElement(defaultElement, resolved);\n}\n"],"mappings":";;;AA2CA,SAAgB,kBAA4B,OAA6B,OAAiB;CACxF,OAAO,OAAO,UAAU,aAAc,MAA8B,KAAK,IAAI;AAC/E;;;;;;;AAQA,SAAgB,cAA4B,QAAuD;CACjG,IAAI,WAAW,KAAA,KAAa,OAAO,WAAW,YAAY,OAAO;CACjE,OAAO,eAAe,MAAM,KAAK,OAAO,SAAS;AACnD;;;;;;;AAQA,SAAgB,eACd,aACA,QAC0B;CAC1B,MAAM,aAAa,eAAiC,MAAM,IAAI,OAAO,MAAM,MAAM,KAAA;CACjF,IAAI,eAAe,QAAQ,cAAc,MAAM,OAAO,UAAU,aAAa,UAAU;CACvF,OAAO,eAAe;AACxB;;;;;;AAOA,SAAgB,cACd,SACW;CACX,MAAM,EAAE,gBAAgB,QAAQ,OAAO,WAAW,OAAO,UAAU,OAAO,cAAc,QACtF;CAEF,MAAM,YAAY;EAChB,GAAG;EACH;EACA,WAAW,kBAAkB,WAAW,KAAK;EAC7C,OAAO,kBAAkB,OAAO,KAAK;EACrC,UAAU,kBAAkB,UAAU,KAAK;CAC7C;CACA,MAAM,aAAc,gBAAgB,CAAC;CAErC,IAAI,eAAiC,MAAM,GAAG;EAE5C,MAAM,EAAE,KAAK,UAAU,GAAG,iBAAiB,OAAO;EAClD,OAAO,aAAa,QAAQ,WAAW,WAAW,cAAc,UAAU,CAAmB;CAC/F;CACA,MAAM,WAAW,WAAW,WAAW,CAAC,GAAG,UAAU;CACrD,IAAI,OAAO,WAAW,YACpB,OAAO,OAAO,UAAU,KAAK;CAE/B,OAAO,cAAc,gBAAgB,QAAQ;AAC/C"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, use } from "react";
|
|
3
|
+
//#region src/internal/toolbar-context.ts
|
|
4
|
+
/**
|
|
5
|
+
* Provided by `Toolbar.Root`; read across folders by `ToggleGroup.Root` (joins the Toolbar's
|
|
6
|
+
* sequence instead of running its own engine), `Toolbar.Separator` (perpendicular orientation)
|
|
7
|
+
* and `Menu.Trigger` (opening arrows in a vertical Toolbar). Conventions 7.1.
|
|
8
|
+
*/
|
|
9
|
+
const ToolbarContext = createContext(null);
|
|
10
|
+
/** The enclosing Toolbar, or `null` outside one. Works during SSR (context, not DOM). */
|
|
11
|
+
function useToolbarContext() {
|
|
12
|
+
return use(ToolbarContext);
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ToolbarContext, useToolbarContext };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=toolbar-context.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolbar-context.mjs","names":[],"sources":["../../src/internal/toolbar-context.ts"],"sourcesContent":["\"use client\";\nimport { createContext, use } from \"react\";\n\n/** What a part inside a `Toolbar.Root` learns about it (design/components/toggle-group.md 7.3, 7.4). */\nexport interface ToolbarContextValue {\n /** The Toolbar's arrow-key axis. */\n readonly orientation: \"horizontal\" | \"vertical\";\n}\n\n/**\n * Provided by `Toolbar.Root`; read across folders by `ToggleGroup.Root` (joins the Toolbar's\n * sequence instead of running its own engine), `Toolbar.Separator` (perpendicular orientation)\n * and `Menu.Trigger` (opening arrows in a vertical Toolbar). Conventions 7.1.\n */\nexport const ToolbarContext = createContext<ToolbarContextValue | null>(null);\n\n/** The enclosing Toolbar, or `null` outside one. Works during SSR (context, not DOM). */\nexport function useToolbarContext(): ToolbarContextValue | null {\n return use(ToolbarContext);\n}\n"],"mappings":";;;;;;;;AAcA,MAAa,iBAAiB,cAA0C,IAAI;;AAG5E,SAAgB,oBAAgD;CAC9D,OAAO,IAAI,cAAc;AAC3B"}
|
|
@@ -7,14 +7,25 @@ function ends(animation) {
|
|
|
7
7
|
return typeof end === "number" && Number.isFinite(end);
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
+
* The animations running in an element's subtree right before it closes (the synchronous
|
|
11
|
+
* `beforetoggle` of the hide, Toast's `data-ending` write): the baseline that `exitAnimations`
|
|
12
|
+
* excludes, so a finite animation already running inside (a progress bar) does not hold the exit
|
|
13
|
+
* (Toast 10.2, #64). Empty where `getAnimations` is absent (jsdom).
|
|
14
|
+
*/
|
|
15
|
+
function animationBaseline(element) {
|
|
16
|
+
if (!element.isConnected || typeof element.getAnimations !== "function") return /* @__PURE__ */ new Set();
|
|
17
|
+
return new Set(element.getAnimations({ subtree: true }));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
10
20
|
* The running exit animations of a top-layer element that has just been hidden, read after a
|
|
11
|
-
* style flush so that `transition-behavior: allow-discrete` exits exist
|
|
12
|
-
*
|
|
21
|
+
* style flush so that `transition-behavior: allow-discrete` exits exist, minus the `baseline`
|
|
22
|
+
* of animations that were already running before the close. Empty where the engine does not
|
|
23
|
+
* animate the exit (Firefox) or there is no CSS exit.
|
|
13
24
|
*/
|
|
14
|
-
function exitAnimations(element) {
|
|
25
|
+
function exitAnimations(element, baseline) {
|
|
15
26
|
if (!element.isConnected || typeof element.getAnimations !== "function") return [];
|
|
16
27
|
getComputedStyle(element).opacity;
|
|
17
|
-
return element.getAnimations({ subtree: true }).filter(ends);
|
|
28
|
+
return element.getAnimations({ subtree: true }).filter((animation) => ends(animation) && !(baseline?.has(animation) ?? false));
|
|
18
29
|
}
|
|
19
30
|
/**
|
|
20
31
|
* The deferred unmount of a top-layer popup's content while its hide animates. `held` is cleared
|
|
@@ -26,6 +37,7 @@ function useExitAnimation() {
|
|
|
26
37
|
const [held, setHeld] = useState(false);
|
|
27
38
|
const wait = useRef(null);
|
|
28
39
|
const generation = useRef(0);
|
|
40
|
+
const baseline = useRef(null);
|
|
29
41
|
const holdUntil = (animations) => {
|
|
30
42
|
const current = ++generation.current;
|
|
31
43
|
wait.current = current;
|
|
@@ -46,10 +58,18 @@ function useExitAnimation() {
|
|
|
46
58
|
holdUntil,
|
|
47
59
|
release,
|
|
48
60
|
holdDuringRender: () => setHeld(true),
|
|
49
|
-
waiting: () => wait.current !== null
|
|
61
|
+
waiting: () => wait.current !== null,
|
|
62
|
+
recordBaseline: (element) => {
|
|
63
|
+
baseline.current = animationBaseline(element);
|
|
64
|
+
},
|
|
65
|
+
exitAnimations: (element) => {
|
|
66
|
+
const recorded = baseline.current ?? void 0;
|
|
67
|
+
baseline.current = null;
|
|
68
|
+
return exitAnimations(element, recorded);
|
|
69
|
+
}
|
|
50
70
|
};
|
|
51
71
|
}
|
|
52
72
|
//#endregion
|
|
53
|
-
export { exitAnimations, useExitAnimation };
|
|
73
|
+
export { animationBaseline, exitAnimations, useExitAnimation };
|
|
54
74
|
|
|
55
75
|
//# sourceMappingURL=use-exit-animation.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-exit-animation.mjs","names":[],"sources":["../../src/internal/use-exit-animation.ts"],"sourcesContent":["\"use client\";\nimport { useRef, useState } from \"react\";\n\n/** An animation that ends: infinite ones (a spinner) would hold the content forever. */\nfunction ends(animation: Animation): boolean {\n const end = animation.effect?.getComputedTiming().endTime;\n return typeof end === \"number\" && Number.isFinite(end);\n}\n\n/**\n * The running exit animations of a top-layer element that has just been hidden, read after a\n * style flush so that `transition-behavior: allow-discrete` exits exist. Empty where the engine\n *
|
|
1
|
+
{"version":3,"file":"use-exit-animation.mjs","names":[],"sources":["../../src/internal/use-exit-animation.ts"],"sourcesContent":["\"use client\";\nimport { useRef, useState } from \"react\";\n\n/** An animation that ends: infinite ones (a spinner) would hold the content forever. */\nfunction ends(animation: Animation): boolean {\n const end = animation.effect?.getComputedTiming().endTime;\n return typeof end === \"number\" && Number.isFinite(end);\n}\n\n/**\n * The animations running in an element's subtree right before it closes (the synchronous\n * `beforetoggle` of the hide, Toast's `data-ending` write): the baseline that `exitAnimations`\n * excludes, so a finite animation already running inside (a progress bar) does not hold the exit\n * (Toast 10.2, #64). Empty where `getAnimations` is absent (jsdom).\n */\nexport function animationBaseline(element: Element): ReadonlySet<Animation> {\n if (!element.isConnected || typeof element.getAnimations !== \"function\") return new Set();\n return new Set(element.getAnimations({ subtree: true }));\n}\n\n/**\n * The running exit animations of a top-layer element that has just been hidden, read after a\n * style flush so that `transition-behavior: allow-discrete` exits exist, minus the `baseline`\n * of animations that were already running before the close. Empty where the engine does not\n * animate the exit (Firefox) or there is no CSS exit.\n */\nexport function exitAnimations(element: Element, baseline?: ReadonlySet<Animation>): Animation[] {\n if (!element.isConnected || typeof element.getAnimations !== \"function\") return [];\n void getComputedStyle(element).opacity;\n return element\n .getAnimations({ subtree: true })\n .filter((animation) => ends(animation) && !(baseline?.has(animation) ?? false));\n}\n\nexport interface ExitAnimation {\n /** Keep the content mounted (design/components/popover.md 4.4). */\n readonly held: boolean;\n /** Set `held` now (urgent, library-internal) and clear it when `animations` settle. */\n readonly holdUntil: (animations: readonly Animation[]) => void;\n /** Clear `held` now (a normal update, never a transition), cancelling any wait in progress. */\n readonly release: () => void;\n /** Set `held` during render (the \"previous value in state\" pattern). */\n readonly holdDuringRender: () => void;\n /** Whether a `holdUntil` wait is still running. Handlers and effects only. */\n readonly waiting: () => boolean;\n /**\n * Record the animations already running in `element`'s subtree. Call from the synchronous\n * `beforetoggle` of a close, before the hide starts the exit (#64).\n */\n readonly recordBaseline: (element: Element) => void;\n /** `exitAnimations(element)` minus the recorded baseline, which it consumes. */\n readonly exitAnimations: (element: Element) => Animation[];\n}\n\n/**\n * The deferred unmount of a top-layer popup's content while its hide animates. `held` is cleared\n * with a normal (urgent) update, never in a transition: the popup is already hidden, nothing\n * visible changes, and only transition commits start a document view transition, so a dismissal\n * runs one (its notification commit) instead of two (design 4.4).\n */\nexport function useExitAnimation(): ExitAnimation {\n const [held, setHeld] = useState(false);\n // The generation of the wait in progress, or null; a newer wait supersedes an older one.\n const wait = useRef<number | null>(null);\n const generation = useRef(0);\n // The animations running right before the latest close (#64), consumed by `exitAnimations`.\n const baseline = useRef<ReadonlySet<Animation> | null>(null);\n\n const holdUntil = (animations: readonly Animation[]): void => {\n const current = ++generation.current;\n wait.current = current;\n setHeld(true);\n void Promise.allSettled(animations.map((animation) => animation.finished)).then(() => {\n if (generation.current !== current) return;\n wait.current = null;\n setHeld(false);\n });\n };\n\n const release = (): void => {\n generation.current++;\n wait.current = null;\n setHeld(false);\n };\n\n return {\n held,\n holdUntil,\n release,\n holdDuringRender: () => setHeld(true),\n waiting: () => wait.current !== null,\n recordBaseline: (element) => {\n baseline.current = animationBaseline(element);\n },\n exitAnimations: (element) => {\n const recorded = baseline.current ?? undefined;\n baseline.current = null;\n return exitAnimations(element, recorded);\n },\n };\n}\n"],"mappings":";;;;AAIA,SAAS,KAAK,WAA+B;CAC3C,MAAM,MAAM,UAAU,QAAQ,kBAAkB,CAAC,CAAC;CAClD,OAAO,OAAO,QAAQ,YAAY,OAAO,SAAS,GAAG;AACvD;;;;;;;AAQA,SAAgB,kBAAkB,SAA0C;CAC1E,IAAI,CAAC,QAAQ,eAAe,OAAO,QAAQ,kBAAkB,YAAY,uBAAO,IAAI,IAAI;CACxF,OAAO,IAAI,IAAI,QAAQ,cAAc,EAAE,SAAS,KAAK,CAAC,CAAC;AACzD;;;;;;;AAQA,SAAgB,eAAe,SAAkB,UAAgD;CAC/F,IAAI,CAAC,QAAQ,eAAe,OAAO,QAAQ,kBAAkB,YAAY,OAAO,CAAC;CACjF,iBAAsB,OAAO,CAAC,CAAC;CAC/B,OAAO,QACJ,cAAc,EAAE,SAAS,KAAK,CAAC,CAAC,CAChC,QAAQ,cAAc,KAAK,SAAS,KAAK,EAAE,UAAU,IAAI,SAAS,KAAK,MAAM;AAClF;;;;;;;AA4BA,SAAgB,mBAAkC;CAChD,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CAEtC,MAAM,OAAO,OAAsB,IAAI;CACvC,MAAM,aAAa,OAAO,CAAC;CAE3B,MAAM,WAAW,OAAsC,IAAI;CAE3D,MAAM,aAAa,eAA2C;EAC5D,MAAM,UAAU,EAAE,WAAW;EAC7B,KAAK,UAAU;EACf,QAAQ,IAAI;EACZ,QAAa,WAAW,WAAW,KAAK,cAAc,UAAU,QAAQ,CAAC,CAAC,CAAC,WAAW;GACpF,IAAI,WAAW,YAAY,SAAS;GACpC,KAAK,UAAU;GACf,QAAQ,KAAK;EACf,CAAC;CACH;CAEA,MAAM,gBAAsB;EAC1B,WAAW;EACX,KAAK,UAAU;EACf,QAAQ,KAAK;CACf;CAEA,OAAO;EACL;EACA;EACA;EACA,wBAAwB,QAAQ,IAAI;EACpC,eAAe,KAAK,YAAY;EAChC,iBAAiB,YAAY;GAC3B,SAAS,UAAU,kBAAkB,OAAO;EAC9C;EACA,iBAAiB,YAAY;GAC3B,MAAM,WAAW,SAAS,WAAW,KAAA;GACrC,SAAS,UAAU;GACnB,OAAO,eAAe,SAAS,QAAQ;EACzC;CACF;AACF"}
|
|
@@ -32,7 +32,7 @@ function useMergedRef(a, b) {
|
|
|
32
32
|
* or the Field's" for `name` / `disabled` / `required`, and returns the owned ARIA wiring.
|
|
33
33
|
*/
|
|
34
34
|
function useFieldControl(options) {
|
|
35
|
-
const { labelable, name, disabled = false, required = false, id, component } = options;
|
|
35
|
+
const { labelable, name, disabled = false, required = false, id, component, validityElement } = options;
|
|
36
36
|
const field = use(FieldContext);
|
|
37
37
|
const registerControl = field?.registerControl;
|
|
38
38
|
const ref = useCallback((element) => {
|
|
@@ -41,13 +41,15 @@ function useFieldControl(options) {
|
|
|
41
41
|
element,
|
|
42
42
|
labelable,
|
|
43
43
|
required,
|
|
44
|
-
disabled
|
|
44
|
+
disabled,
|
|
45
|
+
validityElement
|
|
45
46
|
});
|
|
46
47
|
}, [
|
|
47
48
|
registerControl,
|
|
48
49
|
labelable,
|
|
49
50
|
required,
|
|
50
|
-
disabled
|
|
51
|
+
disabled,
|
|
52
|
+
validityElement
|
|
51
53
|
]);
|
|
52
54
|
useDevWarning(field !== null && id !== void 0, `${component}: the \`id\` prop is ignored inside a Field.Root; the Field owns the control's id so that Field.Label can point at it.`);
|
|
53
55
|
useDevWarning(field !== null && name !== void 0 && field.name !== void 0 && name !== field.name, `${component}: its \`name\` ("${name}") differs from the Field.Root's ("${field?.name}"). The Field reads server errors and \`validate\`'s value by the Field's name.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-field-control.mjs","names":[],"sources":["../../src/internal/use-field-control.ts"],"sourcesContent":["\"use client\";\nimport { use, useCallback, useLayoutEffect, useMemo, useRef } from \"react\";\nimport type { Ref, RefCallback } from \"react\";\nimport { dataAttr } from \"./data-attr.js\";\nimport { FieldContext } from \"./field-context.js\";\nimport type { FieldState } from \"./field-context.js\";\nimport { mergeRefs } from \"./merge-props.js\";\nimport { useDevWarning } from \"./use-dev-warning.js\";\n\nexport interface UseFieldControlOptions {\n /** `<label for>` can target the element (input, select, textarea). Groups pass `false`. */\n readonly labelable: boolean;\n /** The control's own props, so \"own or the Field's\" can be computed. */\n readonly name?: string | undefined;\n readonly disabled?: boolean | undefined;\n readonly required?: boolean | undefined;\n /** The consumer's own `id` prop: ignored inside a Field (the Field owns it), with a warning. */\n readonly id?: string | undefined;\n /** Dev warning tag. */\n readonly component: string;\n}\n\n/** The ARIA and state attributes a part spreads into its owned layer. */\nexport interface FieldControlAttributes {\n /** Labelable controls only: the id `Field.Label`'s `for` points at. */\n id?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: \"true\" | \"false\";\n \"data-invalid\"?: \"\" | undefined;\n}\n\nexport interface FieldControlBinding {\n /** The control is inside a `Field.Root`. */\n readonly inField: boolean;\n /** Merge into the part's library ref: registers the element with the Field. `undefined` outside a Field. */\n readonly ref: RefCallback<HTMLElement> | undefined;\n /** The control id the Field's Label points at (labelable controls inside a Field), else the consumer's. */\n readonly id: string | undefined;\n /** Own `name` ?? the Field's. */\n readonly name: string | undefined;\n /** Own `disabled` || the Field's. */\n readonly disabled: boolean;\n /** Own `required` || the Field's. */\n readonly required: boolean;\n /**\n * Owned attributes: `id` (labelable controls), `aria-invalid`, `data-invalid`,\n * `aria-labelledby` (groups) and `aria-describedby` (both token-merged by the owned layer, the\n * consumer's tokens first). Empty outside a Field, so nothing is owned there.\n */\n readonly attributes: FieldControlAttributes;\n /** The Field's state, `undefined` outside a Field. */\n readonly state: FieldState | undefined;\n}\n\n/**\n * The owned props of a labelable native control (`<input>`, `<select>`) inside a Field: the\n * ARIA wiring plus `name` and `required` (\"own or the Field's\"). Empty outside a Field, so the\n * consumer's own `id` / `name` / `required` keep passing through untouched there.\n */\nexport function fieldInputProps(field: FieldControlBinding): FieldControlAttributes & {\n name?: string | undefined;\n required?: boolean;\n} {\n if (!field.inField) return {};\n return { ...field.attributes, name: field.name, required: field.required };\n}\n\n/** `mergeRefs` with a stable identity while both refs keep theirs. */\nexport function useMergedRef<T>(\n a: Ref<T> | undefined,\n b: Ref<T> | undefined,\n): RefCallback<T> | Ref<T> | undefined {\n return useMemo(() => (b === undefined ? a : a === undefined ? b : mergeRefs(a, b)), [a, b]);\n}\n\n/**\n * The contract between a Field and its control (design/components/field-form.md 7.1), called by\n * `Field.Control` and by the owner part of every FUNSTACK form control. Outside a `Field.Root` it\n * returns the control's own props and nothing to merge.\n *\n * Inside a Field: registers the element from the returned ref (the Field attaches its listeners\n * and reads validity there; a group's `<fieldset>` makes `Field.Label` drop `for`), resolves \"own\n * or the Field's\" for `name` / `disabled` / `required`, and returns the owned ARIA wiring.\n */\nexport function useFieldControl(options: UseFieldControlOptions): FieldControlBinding {\n const {
|
|
1
|
+
{"version":3,"file":"use-field-control.mjs","names":[],"sources":["../../src/internal/use-field-control.ts"],"sourcesContent":["\"use client\";\nimport { use, useCallback, useLayoutEffect, useMemo, useRef } from \"react\";\nimport type { Ref, RefCallback } from \"react\";\nimport { dataAttr } from \"./data-attr.js\";\nimport { FieldContext } from \"./field-context.js\";\nimport type { FieldState } from \"./field-context.js\";\nimport { mergeRefs } from \"./merge-props.js\";\nimport { useDevWarning } from \"./use-dev-warning.js\";\nimport type { ValidatableElement } from \"./validity.js\";\n\nexport interface UseFieldControlOptions {\n /** `<label for>` can target the element (input, select, textarea). Groups pass `false`. */\n readonly labelable: boolean;\n /** The control's own props, so \"own or the Field's\" can be computed. */\n readonly name?: string | undefined;\n readonly disabled?: boolean | undefined;\n readonly required?: boolean | undefined;\n /** The consumer's own `id` prop: ignored inside a Field (the Field owns it), with a warning. */\n readonly id?: string | undefined;\n /** Dev warning tag. */\n readonly component: string;\n /**\n * The element whose validity is real when it is not the registered one (NumberField's hidden\n * number input; field-form.md amendment `validityElement`). Keep its identity stable.\n */\n readonly validityElement?: (() => ValidatableElement | null) | undefined;\n}\n\n/** The ARIA and state attributes a part spreads into its owned layer. */\nexport interface FieldControlAttributes {\n /** Labelable controls only: the id `Field.Label`'s `for` points at. */\n id?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: \"true\" | \"false\";\n \"data-invalid\"?: \"\" | undefined;\n}\n\nexport interface FieldControlBinding {\n /** The control is inside a `Field.Root`. */\n readonly inField: boolean;\n /** Merge into the part's library ref: registers the element with the Field. `undefined` outside a Field. */\n readonly ref: RefCallback<HTMLElement> | undefined;\n /** The control id the Field's Label points at (labelable controls inside a Field), else the consumer's. */\n readonly id: string | undefined;\n /** Own `name` ?? the Field's. */\n readonly name: string | undefined;\n /** Own `disabled` || the Field's. */\n readonly disabled: boolean;\n /** Own `required` || the Field's. */\n readonly required: boolean;\n /**\n * Owned attributes: `id` (labelable controls), `aria-invalid`, `data-invalid`,\n * `aria-labelledby` (groups) and `aria-describedby` (both token-merged by the owned layer, the\n * consumer's tokens first). Empty outside a Field, so nothing is owned there.\n */\n readonly attributes: FieldControlAttributes;\n /** The Field's state, `undefined` outside a Field. */\n readonly state: FieldState | undefined;\n}\n\n/**\n * The owned props of a labelable native control (`<input>`, `<select>`) inside a Field: the\n * ARIA wiring plus `name` and `required` (\"own or the Field's\"). Empty outside a Field, so the\n * consumer's own `id` / `name` / `required` keep passing through untouched there.\n */\nexport function fieldInputProps(field: FieldControlBinding): FieldControlAttributes & {\n name?: string | undefined;\n required?: boolean;\n} {\n if (!field.inField) return {};\n return { ...field.attributes, name: field.name, required: field.required };\n}\n\n/** `mergeRefs` with a stable identity while both refs keep theirs. */\nexport function useMergedRef<T>(\n a: Ref<T> | undefined,\n b: Ref<T> | undefined,\n): RefCallback<T> | Ref<T> | undefined {\n return useMemo(() => (b === undefined ? a : a === undefined ? b : mergeRefs(a, b)), [a, b]);\n}\n\n/**\n * The contract between a Field and its control (design/components/field-form.md 7.1), called by\n * `Field.Control` and by the owner part of every FUNSTACK form control. Outside a `Field.Root` it\n * returns the control's own props and nothing to merge.\n *\n * Inside a Field: registers the element from the returned ref (the Field attaches its listeners\n * and reads validity there; a group's `<fieldset>` makes `Field.Label` drop `for`), resolves \"own\n * or the Field's\" for `name` / `disabled` / `required`, and returns the owned ARIA wiring.\n */\nexport function useFieldControl(options: UseFieldControlOptions): FieldControlBinding {\n const {\n labelable,\n name,\n disabled = false,\n required = false,\n id,\n component,\n validityElement,\n } = options;\n const field = use(FieldContext);\n const registerControl = field?.registerControl;\n\n const ref = useCallback(\n (element: HTMLElement) => {\n if (registerControl === undefined) return () => {};\n return registerControl({ element, labelable, required, disabled, validityElement });\n },\n [registerControl, labelable, required, disabled, validityElement],\n );\n\n useDevWarning(\n field !== null && id !== undefined,\n `${component}: the \\`id\\` prop is ignored inside a Field.Root; the Field owns the control's ` +\n \"id so that Field.Label can point at it.\",\n );\n useDevWarning(\n field !== null && name !== undefined && field.name !== undefined && name !== field.name,\n `${component}: its \\`name\\` (\"${name}\") differs from the Field.Root's (\"${field?.name}\"). ` +\n \"The Field reads server errors and `validate`'s value by the Field's name.\",\n );\n\n if (field === null) {\n return {\n inField: false,\n ref: undefined,\n id,\n name,\n disabled,\n required,\n attributes: {},\n state: undefined,\n };\n }\n\n const { ids, state } = field;\n const attributes: FieldControlAttributes = {\n \"aria-describedby\": state.invalid ? `${ids.description} ${ids.error}` : ids.description,\n \"aria-invalid\": state.invalid ? \"true\" : \"false\",\n \"data-invalid\": dataAttr(state.invalid),\n };\n if (labelable) attributes.id = ids.control;\n else attributes[\"aria-labelledby\"] = ids.label;\n\n return {\n inField: true,\n ref: ref as RefCallback<HTMLElement>,\n id: labelable ? ids.control : undefined,\n name: name ?? field.name,\n disabled: disabled || field.disabled,\n required: required || field.required,\n attributes,\n state,\n };\n}\n\n/**\n * Tells the enclosing Field (if any) that the control's value changed, after the commit that\n * wrote it to the DOM (design/components/field-form.md 2.1: `validate` and the mirror follow the\n * value). Needed where the DOM changes without an `input` / `change` event the Field hears: a\n * Combobox selection (React writes the hidden input), a CheckboxGroup's derived `required`, a\n * Parent checking Items, a rejected action rolling the value back. Nothing at mount.\n *\n * `takeEdit` is read when the value changed: `true` when the user made this change (a shown\n * server error is dismissed, like an `input` event would). Native controls whose own events\n * already dismiss pass nothing.\n */\nexport function useFieldValueChange(value: unknown, takeEdit?: () => boolean): void {\n const notifyChange = use(FieldContext)?.notifyChange;\n const previous = useRef(value);\n // No deps: compares with the last committed value after every commit of the caller.\n useLayoutEffect(() => {\n if (Object.is(previous.current, value)) return;\n previous.current = value;\n const edit = takeEdit?.() ?? false;\n notifyChange?.(edit);\n });\n}\n"],"mappings":";;;;;;;;;;;;AAkEA,SAAgB,gBAAgB,OAG9B;CACA,IAAI,CAAC,MAAM,SAAS,OAAO,CAAC;CAC5B,OAAO;EAAE,GAAG,MAAM;EAAY,MAAM,MAAM;EAAM,UAAU,MAAM;CAAS;AAC3E;;AAGA,SAAgB,aACd,GACA,GACqC;CACrC,OAAO,cAAe,MAAM,KAAA,IAAY,IAAI,MAAM,KAAA,IAAY,IAAI,UAAU,GAAG,CAAC,GAAI,CAAC,GAAG,CAAC,CAAC;AAC5F;;;;;;;;;;AAWA,SAAgB,gBAAgB,SAAsD;CACpF,MAAM,EACJ,WACA,MACA,WAAW,OACX,WAAW,OACX,IACA,WACA,oBACE;CACJ,MAAM,QAAQ,IAAI,YAAY;CAC9B,MAAM,kBAAkB,OAAO;CAE/B,MAAM,MAAM,aACT,YAAyB;EACxB,IAAI,oBAAoB,KAAA,GAAW,aAAa,CAAC;EACjD,OAAO,gBAAgB;GAAE;GAAS;GAAW;GAAU;GAAU;EAAgB,CAAC;CACpF,GACA;EAAC;EAAiB;EAAW;EAAU;EAAU;CAAe,CAClE;CAEA,cACE,UAAU,QAAQ,OAAO,KAAA,GACzB,GAAG,UAAU,uHAEf;CACA,cACE,UAAU,QAAQ,SAAS,KAAA,KAAa,MAAM,SAAS,KAAA,KAAa,SAAS,MAAM,MACnF,GAAG,UAAU,mBAAmB,KAAK,qCAAqC,OAAO,KAAK,gFAExF;CAEA,IAAI,UAAU,MACZ,OAAO;EACL,SAAS;EACT,KAAK,KAAA;EACL;EACA;EACA;EACA;EACA,YAAY,CAAC;EACb,OAAO,KAAA;CACT;CAGF,MAAM,EAAE,KAAK,UAAU;CACvB,MAAM,aAAqC;EACzC,oBAAoB,MAAM,UAAU,GAAG,IAAI,YAAY,GAAG,IAAI,UAAU,IAAI;EAC5E,gBAAgB,MAAM,UAAU,SAAS;EACzC,gBAAgB,SAAS,MAAM,OAAO;CACxC;CACA,IAAI,WAAW,WAAW,KAAK,IAAI;MAC9B,WAAW,qBAAqB,IAAI;CAEzC,OAAO;EACL,SAAS;EACJ;EACL,IAAI,YAAY,IAAI,UAAU,KAAA;EAC9B,MAAM,QAAQ,MAAM;EACpB,UAAU,YAAY,MAAM;EAC5B,UAAU,YAAY,MAAM;EAC5B;EACA;CACF;AACF;;;;;;;;;;;;AAaA,SAAgB,oBAAoB,OAAgB,UAAgC;CAClF,MAAM,eAAe,IAAI,YAAY,CAAC,EAAE;CACxC,MAAM,WAAW,OAAO,KAAK;CAE7B,sBAAsB;EACpB,IAAI,OAAO,GAAG,SAAS,SAAS,KAAK,GAAG;EACxC,SAAS,UAAU;EACnB,MAAM,OAAO,WAAW,KAAK;EAC7B,eAAe,IAAI;CACrB,CAAC;AACH"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useContentFocusProbe } from "./content-focus-probe.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { useExitAnimation } from "./use-exit-animation.mjs";
|
|
4
4
|
import { useCallback, useEffect, useEffectEvent, useInsertionEffect, useLayoutEffect, useRef, useState } from "react";
|
|
5
5
|
//#region src/internal/use-popover-popup.ts
|
|
6
6
|
const isDev = process.env.NODE_ENV !== "production";
|
|
@@ -154,6 +154,7 @@ function usePopoverPopup(ctx, options) {
|
|
|
154
154
|
contentProbe.forget();
|
|
155
155
|
} else {
|
|
156
156
|
awaitingClose.current = true;
|
|
157
|
+
exit.recordBaseline(element);
|
|
157
158
|
const active = element.ownerDocument.activeElement;
|
|
158
159
|
focusWasInside.current = active !== null && element.contains(active) || contentProbe.hadFocus();
|
|
159
160
|
contentProbe.forget();
|
|
@@ -172,7 +173,7 @@ function usePopoverPopup(ctx, options) {
|
|
|
172
173
|
const intent = ctx.takeCloseIntent();
|
|
173
174
|
if (isLibrary) {
|
|
174
175
|
if (!!ctx.intended() || transition === void 0) {
|
|
175
|
-
const animations = exitAnimations(element);
|
|
176
|
+
const animations = exit.exitAnimations(element);
|
|
176
177
|
if (animations.length > 0) exit.holdUntil(animations);
|
|
177
178
|
else exit.release();
|
|
178
179
|
}
|