@octanejs/base-ui 0.1.1 → 0.1.3
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/README.md +7 -1
- package/package.json +12 -4
- package/src/alert-dialog.ts +47 -0
- package/src/checkbox.ts +7 -16
- package/src/dialog.ts +859 -0
- package/src/field.ts +4 -30
- package/src/index.ts +3 -0
- package/src/number-field.ts +8 -45
- package/src/popover.ts +1205 -0
- package/src/radio.ts +3 -24
- package/src/slider.ts +4 -5
- package/src/switch.ts +4 -30
- package/src/utils/InternalBackdrop.ts +28 -0
- package/src/utils/adaptiveOriginMiddleware.ts +82 -0
- package/src/utils/closePart.ts +61 -0
- package/src/utils/constants.ts +9 -0
- package/src/utils/createChangeEventDetails.ts +7 -0
- package/src/utils/dom.ts +9 -0
- package/src/utils/empty.ts +7 -0
- package/src/utils/floating/FloatingFocusManager.ts +833 -0
- package/src/utils/floating/FloatingPortal.ts +268 -0
- package/src/utils/floating/FloatingRootStore.ts +127 -0
- package/src/utils/floating/FloatingTree.ts +70 -0
- package/src/utils/floating/FloatingTreeStore.ts +22 -0
- package/src/utils/floating/FocusGuard.ts +34 -0
- package/src/utils/floating/composite.ts +20 -0
- package/src/utils/floating/constants.ts +8 -0
- package/src/utils/floating/createAttribute.ts +4 -0
- package/src/utils/floating/createEventEmitter.ts +20 -0
- package/src/utils/floating/element.ts +54 -0
- package/src/utils/floating/enqueueFocus.ts +38 -0
- package/src/utils/floating/event.ts +53 -0
- package/src/utils/floating/getEmptyRootContext.ts +19 -0
- package/src/utils/floating/markOthers.ts +197 -0
- package/src/utils/floating/nodes.ts +31 -0
- package/src/utils/floating/tabbable.ts +260 -0
- package/src/utils/floating/types.ts +57 -0
- package/src/utils/floating/useClick.ts +174 -0
- package/src/utils/floating/useDismiss.ts +641 -0
- package/src/utils/floating/useFloating.ts +198 -0
- package/src/utils/floating/useFloatingRootContext.ts +81 -0
- package/src/utils/floating/useHoverFloatingInteraction.ts +12 -0
- package/src/utils/floating/useHoverReferenceInteraction.ts +17 -0
- package/src/utils/floating/useSyncedFloatingRootContext.ts +93 -0
- package/src/utils/getDisabledMountTransitionStyles.ts +12 -0
- package/src/utils/hideMiddleware.ts +22 -0
- package/src/utils/inertValue.ts +5 -0
- package/src/utils/mergeCleanups.ts +13 -0
- package/src/utils/platform.ts +46 -2
- package/src/utils/popupStateMapping.ts +48 -0
- package/src/utils/popups/index.ts +4 -0
- package/src/utils/popups/popupStoreUtils.ts +484 -0
- package/src/utils/popups/popupTriggerMap.ts +62 -0
- package/src/utils/popups/store.ts +147 -0
- package/src/utils/popups/useTriggerFocusGuards.ts +73 -0
- package/src/utils/store/ReactStore.ts +168 -0
- package/src/utils/store/Store.ts +84 -0
- package/src/utils/store/createSelector.ts +66 -0
- package/src/utils/store/useStore.ts +49 -0
- package/src/utils/useAnchorPositioning.ts +581 -0
- package/src/utils/useAnchoredPopupScrollLock.ts +50 -0
- package/src/utils/useAnimationFrame.ts +28 -5
- package/src/utils/useEnhancedClickHandler.ts +47 -0
- package/src/utils/useOnFirstRender.ts +11 -0
- package/src/utils/useOpenInteractionType.ts +32 -0
- package/src/utils/usePositioner.ts +48 -0
- package/src/utils/useScrollLock.ts +253 -0
package/src/field.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
//
|
|
5
5
|
// Field groups a control with its label/description/error and runs validation. The default
|
|
6
6
|
// (inert) field contexts are overridden here by the real providers. octane adaptations:
|
|
7
|
-
// native events; forwardRef → ref-as-prop
|
|
8
|
-
//
|
|
7
|
+
// native events; forwardRef → ref-as-prop. The control's `value`/`defaultValue` pass straight
|
|
8
|
+
// through — octane inputs are CONTROLLED exactly like React's.
|
|
9
9
|
import {
|
|
10
10
|
createContext,
|
|
11
11
|
createElement,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
|
|
21
21
|
import { S, subSlot } from './internal';
|
|
22
22
|
import { useRenderElement, type RenderProp } from './utils/useRenderElement';
|
|
23
|
-
import { ownerDocument
|
|
23
|
+
import { ownerDocument } from './utils/owner';
|
|
24
24
|
import { createChangeEventDetails, REASONS } from './utils/createChangeEventDetails';
|
|
25
25
|
import { useControlled } from './utils/useControlled';
|
|
26
26
|
import { useStableCallback } from './utils/useStableCallback';
|
|
@@ -341,32 +341,6 @@ function FieldControl(props: any): any {
|
|
|
341
341
|
const isControlled = valueProp !== undefined;
|
|
342
342
|
const value = isControlled ? valueUnwrapped : undefined;
|
|
343
343
|
|
|
344
|
-
// octane text-input adaptation: the INITIAL value is the `value` ATTRIBUTE; a controlled
|
|
345
|
-
// value is driven imperatively via the property.
|
|
346
|
-
const initialValueRef = useRef(
|
|
347
|
-
isControlled ? value : defaultValue,
|
|
348
|
-
subSlot(slot, 'initialValue'),
|
|
349
|
-
);
|
|
350
|
-
|
|
351
|
-
useLayoutEffect(
|
|
352
|
-
() => {
|
|
353
|
-
if (!isControlled) {
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
const input = validation.inputRef.current;
|
|
357
|
-
if (!input) {
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
const setNativeValue = Object.getOwnPropertyDescriptor(
|
|
361
|
-
ownerWindow(input).HTMLInputElement.prototype,
|
|
362
|
-
'value',
|
|
363
|
-
)?.set;
|
|
364
|
-
setNativeValue?.call(input, value ?? '');
|
|
365
|
-
},
|
|
366
|
-
[isControlled, value],
|
|
367
|
-
subSlot(slot, 'e:syncValue'),
|
|
368
|
-
);
|
|
369
|
-
|
|
370
344
|
const getValueFromInput = useStableCallback(
|
|
371
345
|
() => validation.inputRef.current?.value,
|
|
372
346
|
subSlot(slot, 'getValue'),
|
|
@@ -396,7 +370,7 @@ function FieldControl(props: any): any {
|
|
|
396
370
|
ref: validation.inputRef,
|
|
397
371
|
'aria-labelledby': labelId,
|
|
398
372
|
autoFocus: autoFocus || undefined,
|
|
399
|
-
value:
|
|
373
|
+
...(isControlled ? { value } : { defaultValue }),
|
|
400
374
|
onChange(event: any) {
|
|
401
375
|
const inputValue = event.currentTarget.value;
|
|
402
376
|
onValueChange?.(inputValue, createChangeEventDetails(REASONS.none, event));
|
package/src/index.ts
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
// (`@octanejs/base-ui/separator`, `@octanejs/base-ui/use-render`, …). This barrel
|
|
4
4
|
// re-exports the public surface for convenience as components land.
|
|
5
5
|
export { Separator } from './separator';
|
|
6
|
+
export { AlertDialog } from './alert-dialog';
|
|
6
7
|
export { Avatar } from './avatar';
|
|
7
8
|
export { Checkbox } from './checkbox';
|
|
8
9
|
export { CheckboxGroup } from './checkbox-group';
|
|
10
|
+
export { Dialog } from './dialog';
|
|
9
11
|
export { Field } from './field';
|
|
10
12
|
export { Fieldset } from './fieldset';
|
|
11
13
|
export { Form } from './form';
|
|
@@ -15,6 +17,7 @@ export { NumberField } from './number-field';
|
|
|
15
17
|
export { Progress } from './progress';
|
|
16
18
|
export { Radio } from './radio';
|
|
17
19
|
export { RadioGroup } from './radio-group';
|
|
20
|
+
export { Popover } from './popover';
|
|
18
21
|
export { Slider } from './slider';
|
|
19
22
|
export { Switch } from './switch';
|
|
20
23
|
export { Toggle } from './toggle';
|
package/src/number-field.ts
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
// decrement/NumberFieldDecrement, root/useNumberFieldButton + useNumberFieldStepperButton, and
|
|
4
4
|
// utils/stateAttributesMapping — plus its `index.parts` (the `NumberField` namespace).
|
|
5
5
|
//
|
|
6
|
-
// octane adaptations: native events (no `.nativeEvent`); forwardRef → ref-as-prop
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
6
|
+
// octane adaptations: native events (no `.nativeEvent`); forwardRef → ref-as-prop. The visible
|
|
7
|
+
// and hidden inputs take live controlled `value` props — octane inputs are CONTROLLED exactly
|
|
8
|
+
// like React's (property-driven, reasserted on every commit and after discrete events). The
|
|
9
|
+
// scrub area + press-and-hold auto-repeat are deferred (see `usePressAndHold` stub).
|
|
10
|
+
// Field/Form integration is inert when standalone.
|
|
10
11
|
import {
|
|
11
12
|
createContext,
|
|
12
13
|
createElement,
|
|
@@ -29,7 +30,7 @@ import { useValueChanged } from './utils/useValueChanged';
|
|
|
29
30
|
import { useForcedRerendering } from './utils/useForcedRerendering';
|
|
30
31
|
import { addEventListener } from './utils/addEventListener';
|
|
31
32
|
import { platform } from './utils/platform';
|
|
32
|
-
import { ownerDocument
|
|
33
|
+
import { ownerDocument } from './utils/owner';
|
|
33
34
|
import { visuallyHidden, visuallyHiddenInput } from './utils/visuallyHidden';
|
|
34
35
|
import { stopEvent } from './utils/composite/list-utils';
|
|
35
36
|
import { useButton } from './utils/useButton';
|
|
@@ -212,9 +213,6 @@ function NumberFieldRoot(props: any): any {
|
|
|
212
213
|
);
|
|
213
214
|
const [inputMode, setInputMode] = useState<InputMode>('numeric', subSlot(slot, 'inputMode'));
|
|
214
215
|
|
|
215
|
-
// octane: reflect the INITIAL numeric value as the hidden input's `value` ATTRIBUTE.
|
|
216
|
-
const initialHiddenValueRef = useRef(value ?? '', subSlot(slot, 'initialHidden'));
|
|
217
|
-
|
|
218
216
|
const getAllowedNonNumericKeys = useStableCallback(
|
|
219
217
|
() => {
|
|
220
218
|
const { decimal, group, currency, literal } = getNumberLocaleDetails(locale, format);
|
|
@@ -467,8 +465,7 @@ function NumberFieldRoot(props: any): any {
|
|
|
467
465
|
type: 'number',
|
|
468
466
|
form,
|
|
469
467
|
name,
|
|
470
|
-
|
|
471
|
-
value: initialHiddenValueRef.current,
|
|
468
|
+
value: value ?? '',
|
|
472
469
|
min,
|
|
473
470
|
max,
|
|
474
471
|
step: stepProp,
|
|
@@ -480,21 +477,6 @@ function NumberFieldRoot(props: any): any {
|
|
|
480
477
|
style: name ? visuallyHiddenInput : visuallyHidden,
|
|
481
478
|
});
|
|
482
479
|
|
|
483
|
-
// octane: drive the hidden input's live `.value` PROPERTY.
|
|
484
|
-
useLayoutEffect(
|
|
485
|
-
() => {
|
|
486
|
-
const el = validation.inputRef.current ?? inputRef.current;
|
|
487
|
-
if (!el) return;
|
|
488
|
-
const setNativeValue = Object.getOwnPropertyDescriptor(
|
|
489
|
-
ownerWindow(el).HTMLInputElement.prototype,
|
|
490
|
-
'value',
|
|
491
|
-
)?.set;
|
|
492
|
-
setNativeValue?.call(el, value ?? '');
|
|
493
|
-
},
|
|
494
|
-
[value],
|
|
495
|
-
subSlot(slot, 'e:syncHidden'),
|
|
496
|
-
);
|
|
497
|
-
|
|
498
480
|
return createElement(NumberFieldRootContext.Provider, {
|
|
499
481
|
value: contextValue,
|
|
500
482
|
children: [element, hiddenInput],
|
|
@@ -558,9 +540,6 @@ function NumberFieldInput(props: any): any {
|
|
|
558
540
|
const blockRevalidationRef = useRef(false, subSlot(slot, 'blockReval'));
|
|
559
541
|
const pendingCaretRef = useRef<number | null>(null, subSlot(slot, 'caret'));
|
|
560
542
|
|
|
561
|
-
// octane: reflect the INITIAL formatted text as the `value` ATTRIBUTE; live via the property.
|
|
562
|
-
const initialInputValueRef = useRef(inputValue, subSlot(slot, 'initialInput'));
|
|
563
|
-
|
|
564
543
|
useRegisterFieldControl(
|
|
565
544
|
inputRef,
|
|
566
545
|
id,
|
|
@@ -583,21 +562,6 @@ function NumberFieldInput(props: any): any {
|
|
|
583
562
|
subSlot(slot, 'e:caret'),
|
|
584
563
|
);
|
|
585
564
|
|
|
586
|
-
// octane: drive the visible input's live `.value` PROPERTY (matches React's controlled input).
|
|
587
|
-
useLayoutEffect(
|
|
588
|
-
() => {
|
|
589
|
-
const el = inputRef.current;
|
|
590
|
-
if (!el) return;
|
|
591
|
-
const setNativeValue = Object.getOwnPropertyDescriptor(
|
|
592
|
-
ownerWindow(el).HTMLInputElement.prototype,
|
|
593
|
-
'value',
|
|
594
|
-
)?.set;
|
|
595
|
-
setNativeValue?.call(el, inputValue);
|
|
596
|
-
},
|
|
597
|
-
[inputValue],
|
|
598
|
-
subSlot(slot, 'e:syncValue'),
|
|
599
|
-
);
|
|
600
|
-
|
|
601
565
|
useValueChanged(
|
|
602
566
|
value,
|
|
603
567
|
() => {
|
|
@@ -617,8 +581,7 @@ function NumberFieldInput(props: any): any {
|
|
|
617
581
|
disabled,
|
|
618
582
|
readOnly,
|
|
619
583
|
inputMode,
|
|
620
|
-
|
|
621
|
-
value: initialInputValueRef.current,
|
|
584
|
+
value: inputValue,
|
|
622
585
|
type: 'text',
|
|
623
586
|
autoComplete: 'off',
|
|
624
587
|
autoCorrect: 'off',
|