@pathscale/ui 1.1.78 → 1.1.80

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.
@@ -1,20 +1,70 @@
1
1
  import { type Component, type JSX } from "solid-js";
2
2
  import type { IComponentBaseProps } from "../types";
3
3
  export type PasswordFieldProps = IComponentBaseProps & {
4
+ id?: string;
4
5
  name?: string;
5
6
  label?: JSX.Element;
6
7
  placeholder?: string;
7
8
  disabled?: boolean;
8
9
  invalid?: boolean;
10
+ required?: boolean;
11
+ autofocus?: boolean;
9
12
  autocomplete?: "current-password" | "new-password" | "off";
13
+ "aria-describedby"?: string;
10
14
  startIcon?: JSX.Element;
11
15
  showLabel: string;
12
16
  hideLabel: string;
13
17
  value?: string;
18
+ inputRef?: (el: HTMLInputElement) => void;
14
19
  onInput?: (value: string) => void;
15
20
  onBlur?: () => void;
21
+ visibleIcon?: JSX.Element;
22
+ hiddenIcon?: JSX.Element;
23
+ onVisibilityChange?: (visible: boolean) => void;
16
24
  class?: string;
17
25
  inputClass?: string;
18
26
  };
27
+ export type PasswordToggleSnapshot = {
28
+ hadFocus: boolean;
29
+ selectionStart: number | null;
30
+ selectionEnd: number | null;
31
+ selectionDirection: "forward" | "backward" | "none" | null;
32
+ valueBeforeToggle: string | null;
33
+ };
34
+ type PasswordFieldInputContractParams = Pick<PasswordFieldProps, "id" | "name" | "label" | "placeholder" | "required" | "autofocus" | "autocomplete" | "aria-describedby" | "value" | "disabled" | "invalid" | "startIcon" | "inputClass"> & {
35
+ isVisible: boolean;
36
+ };
37
+ export declare const createPasswordFieldInputContract: (params: PasswordFieldInputContractParams) => {
38
+ id: string | undefined;
39
+ name: string | undefined;
40
+ label: JSX.Element;
41
+ type: string;
42
+ placeholder: string | undefined;
43
+ required: boolean | undefined;
44
+ autofocus: boolean | undefined;
45
+ autocomplete: "off" | "current-password" | "new-password" | undefined;
46
+ "aria-describedby": string | undefined;
47
+ value: string | undefined;
48
+ isDisabled: boolean;
49
+ isInvalid: boolean;
50
+ startIcon: JSX.Element;
51
+ class: string;
52
+ };
53
+ type PasswordFieldLike = {
54
+ value: string;
55
+ selectionStart: number | null;
56
+ selectionEnd: number | null;
57
+ selectionDirection: "forward" | "backward" | "none" | null;
58
+ focus: (options?: {
59
+ preventScroll?: boolean;
60
+ }) => void;
61
+ setSelectionRange: (selectionStart: number, selectionEnd: number, selectionDirection?: "forward" | "backward" | "none") => void;
62
+ dispatchEvent: (event: Event) => boolean;
63
+ };
64
+ export declare const getPasswordInputType: (isVisible: boolean) => "text" | "password";
65
+ export declare const selectPasswordToggleIcon: (isVisible: boolean, visibleIcon: JSX.Element | undefined, hiddenIcon: JSX.Element | undefined, fallback: JSX.Element) => JSX.Element;
66
+ export declare const capturePasswordToggleSnapshot: (field: PasswordFieldLike | undefined, activeElement: EventTarget | null) => PasswordToggleSnapshot;
67
+ export declare const restorePasswordFieldAfterToggle: (field: PasswordFieldLike | undefined, snapshot: PasswordToggleSnapshot) => void;
68
+ export declare const preventPasswordTogglePointerDown: (event: Pick<PointerEvent, "preventDefault">) => void;
19
69
  declare const PasswordField: Component<PasswordFieldProps>;
20
70
  export default PasswordField;
@@ -5,27 +5,100 @@ import * as __WEBPACK_EXTERNAL_MODULE__button_index_js_557db1f7__ from "../butto
5
5
  import * as __WEBPACK_EXTERNAL_MODULE__icon_index_js_1f7a158c__ from "../icon/index.js";
6
6
  import * as __WEBPACK_EXTERNAL_MODULE__input_index_js_00da0e74__ from "../input/index.js";
7
7
  var _tmpl$ = /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.template)("<div>");
8
- const PasswordField_PasswordField = (props)=>{
8
+ const createPasswordFieldInputContract = (params)=>({
9
+ id: params.id,
10
+ name: params.name,
11
+ label: params.label,
12
+ type: getPasswordInputType(params.isVisible),
13
+ placeholder: params.placeholder,
14
+ required: params.required,
15
+ autofocus: params.autofocus,
16
+ autocomplete: params.autocomplete,
17
+ "aria-describedby": params["aria-describedby"],
18
+ value: params.value,
19
+ isDisabled: Boolean(params.disabled),
20
+ isInvalid: Boolean(params.invalid),
21
+ startIcon: params.startIcon,
22
+ class: (0, __WEBPACK_EXTERNAL_MODULE_tailwind_merge_e05e3e95__.twMerge)("w-full", params.inputClass)
23
+ });
24
+ const getPasswordInputType = (isVisible)=>isVisible ? "text" : "password";
25
+ const selectPasswordToggleIcon = (isVisible, visibleIcon, hiddenIcon, fallback)=>(isVisible ? visibleIcon : hiddenIcon) ?? fallback;
26
+ const capturePasswordToggleSnapshot = (field, activeElement)=>({
27
+ hadFocus: activeElement === field,
28
+ selectionStart: field?.selectionStart ?? null,
29
+ selectionEnd: field?.selectionEnd ?? null,
30
+ selectionDirection: field?.selectionDirection ?? null,
31
+ valueBeforeToggle: field?.value ?? null
32
+ });
33
+ const restorePasswordFieldAfterToggle = (field, snapshot)=>{
34
+ if (!field) return;
35
+ if (null !== snapshot.valueBeforeToggle && field.value !== snapshot.valueBeforeToggle) {
36
+ field.value = snapshot.valueBeforeToggle;
37
+ field.dispatchEvent(new Event("input", {
38
+ bubbles: true
39
+ }));
40
+ }
41
+ if (!snapshot.hadFocus) return;
42
+ field.focus({
43
+ preventScroll: true
44
+ });
45
+ if (null === snapshot.selectionStart || null === snapshot.selectionEnd) return;
46
+ try {
47
+ field.setSelectionRange(snapshot.selectionStart, snapshot.selectionEnd, snapshot.selectionDirection ?? void 0);
48
+ } catch {}
49
+ };
50
+ const preventPasswordTogglePointerDown = (event)=>event.preventDefault();
51
+ const PasswordField = (props)=>{
9
52
  const [local] = (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.splitProps)(props, [
53
+ "id",
10
54
  "name",
11
55
  "label",
12
56
  "placeholder",
13
57
  "disabled",
14
58
  "invalid",
59
+ "required",
60
+ "autofocus",
15
61
  "autocomplete",
62
+ "aria-describedby",
16
63
  "startIcon",
17
64
  "showLabel",
18
65
  "hideLabel",
19
66
  "value",
67
+ "inputRef",
20
68
  "onInput",
21
69
  "onBlur",
70
+ "visibleIcon",
71
+ "hiddenIcon",
72
+ "onVisibilityChange",
22
73
  "inputClass",
23
74
  "class",
24
75
  "className",
25
76
  "dataTheme"
26
77
  ]);
27
78
  const [isVisible, setIsVisible] = (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.createSignal)(false);
79
+ let fieldRef;
28
80
  const toggleLabel = ()=>isVisible() ? local.hideLabel : local.showLabel;
81
+ const toggleIcon = ()=>selectPasswordToggleIcon(isVisible(), local.visibleIcon, local.hiddenIcon, (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.createComponent)(__WEBPACK_EXTERNAL_MODULE__icon_index_js_1f7a158c__["default"], {
82
+ width: 16,
83
+ height: 16,
84
+ get name () {
85
+ return isVisible() ? "icon-[lucide--eye-off]" : "icon-[lucide--eye]";
86
+ },
87
+ class: "h-4 w-4"
88
+ }));
89
+ const setFieldRef = (el)=>{
90
+ fieldRef = el;
91
+ local.inputRef?.(el);
92
+ };
93
+ const toggleVisibility = ()=>{
94
+ const snapshot = capturePasswordToggleSnapshot(fieldRef, "undefined" != typeof document ? document.activeElement : null);
95
+ const nextVisible = !isVisible();
96
+ setIsVisible(nextVisible);
97
+ local.onVisibilityChange?.(nextVisible);
98
+ queueMicrotask(()=>{
99
+ restorePasswordFieldAfterToggle(fieldRef, snapshot);
100
+ });
101
+ };
29
102
  return (()=>{
30
103
  var _el$ = _tmpl$();
31
104
  (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.spread)(_el$, (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.mergeProps)(()=>({
@@ -39,41 +112,27 @@ const PasswordField_PasswordField = (props)=>{
39
112
  return isVisible() ? "true" : "false";
40
113
  }
41
114
  }), false, true);
42
- (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.insert)(_el$, (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.createComponent)(__WEBPACK_EXTERNAL_MODULE__input_index_js_00da0e74__["default"], (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.mergeProps)({
43
- get name () {
44
- return local.name;
45
- },
46
- get label () {
47
- return local.label;
48
- },
49
- get type () {
50
- return isVisible() ? "text" : "password";
51
- },
52
- get placeholder () {
53
- return local.placeholder;
54
- },
55
- get autocomplete () {
56
- return local.autocomplete;
57
- },
58
- get value () {
59
- return local.value;
60
- },
61
- get isDisabled () {
62
- return Boolean(local.disabled);
63
- },
64
- get isInvalid () {
65
- return Boolean(local.invalid);
66
- },
67
- get startIcon () {
68
- return local.startIcon;
69
- },
115
+ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.insert)(_el$, (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.createComponent)(__WEBPACK_EXTERNAL_MODULE__input_index_js_00da0e74__["default"], (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.mergeProps)(()=>createPasswordFieldInputContract({
116
+ id: local.id,
117
+ name: local.name,
118
+ label: local.label,
119
+ isVisible: isVisible(),
120
+ placeholder: local.placeholder,
121
+ required: local.required,
122
+ autofocus: local.autofocus,
123
+ autocomplete: local.autocomplete,
124
+ "aria-describedby": local["aria-describedby"],
125
+ value: local.value,
126
+ disabled: local.disabled,
127
+ invalid: local.invalid,
128
+ startIcon: local.startIcon,
129
+ inputClass: local.inputClass
130
+ }), {
131
+ ref: setFieldRef,
70
132
  onInput: (event)=>{
71
133
  local.onInput?.(event.currentTarget.value);
72
134
  },
73
- onBlur: ()=>local.onBlur?.()
74
- }, ()=>({
75
- class: (0, __WEBPACK_EXTERNAL_MODULE_tailwind_merge_e05e3e95__.twMerge)("w-full", local.inputClass)
76
- }), {
135
+ onBlur: ()=>local.onBlur?.(),
77
136
  get endIcon () {
78
137
  return (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.createComponent)(__WEBPACK_EXTERNAL_MODULE__button_index_js_557db1f7__["default"], {
79
138
  type: "button",
@@ -81,7 +140,11 @@ const PasswordField_PasswordField = (props)=>{
81
140
  size: "sm",
82
141
  isIconOnly: true,
83
142
  class: "h-7 min-h-7 w-7 min-w-7",
84
- onClick: ()=>setIsVisible((value)=>!value),
143
+ get isDisabled () {
144
+ return Boolean(local.disabled);
145
+ },
146
+ onPointerDown: preventPasswordTogglePointerDown,
147
+ onClick: toggleVisibility,
85
148
  get ["aria-label"] () {
86
149
  return toggleLabel();
87
150
  },
@@ -92,14 +155,7 @@ const PasswordField_PasswordField = (props)=>{
92
155
  return toggleLabel();
93
156
  },
94
157
  get children () {
95
- return (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.createComponent)(__WEBPACK_EXTERNAL_MODULE__icon_index_js_1f7a158c__["default"], {
96
- width: 16,
97
- height: 16,
98
- get name () {
99
- return isVisible() ? "icon-[lucide--eye-off]" : "icon-[lucide--eye]";
100
- },
101
- class: "h-4 w-4"
102
- });
158
+ return toggleIcon();
103
159
  }
104
160
  });
105
161
  }
@@ -107,5 +163,5 @@ const PasswordField_PasswordField = (props)=>{
107
163
  return _el$;
108
164
  })();
109
165
  };
110
- const PasswordField = PasswordField_PasswordField;
111
- export { PasswordField as default };
166
+ const password_field_PasswordField = PasswordField;
167
+ export { capturePasswordToggleSnapshot, createPasswordFieldInputContract, password_field_PasswordField as default, getPasswordInputType, preventPasswordTogglePointerDown, restorePasswordFieldAfterToggle, selectPasswordToggleIcon };
@@ -6,6 +6,8 @@ export { prefersReducedMotion } from "./reduced-motion";
6
6
  export { defaultMotionTokens, mergeMotionTokens, motionDurations, motionDistances, motionEasings, } from "./tokens";
7
7
  export { getPreset, createMotionPresets, motionPresets, noMotion, registerPreset, resolvePreset, routeTransition, } from "./presets";
8
8
  export { MotionDiv, type MotionDivProps } from "./solid";
9
+ export { Presence, nextPresenceState, type PresenceProps, type PresenceRenderProp, } from "./solid";
10
+ export { AnimatedCollapse, nextCollapsePhase, computeCollapseStyle, type AnimatedCollapseProps, } from "./solid";
9
11
  export { createPopmotionDriver, enablePopmotion, type PopmotionAnimate, } from "./popmotion";
10
12
  export { createMotionSystem, type MotionSystemConfig } from "./system";
11
13
  export { createRouteTransitionResolver, type RouteTransitionRule, type RouteTransitionRuleResult, type RouteTransitionResolverOptions, } from "./route";
@@ -8,7 +8,10 @@ import * as __WEBPACK_EXTERNAL_MODULE__solid_index_js_0e5c9791__ from "./solid/i
8
8
  import * as __WEBPACK_EXTERNAL_MODULE__popmotion_js_a3c50ca9__ from "./popmotion.js";
9
9
  import * as __WEBPACK_EXTERNAL_MODULE__system_js_50c29608__ from "./system.js";
10
10
  import * as __WEBPACK_EXTERNAL_MODULE__route_js_d0361f8a__ from "./route.js";
11
+ var __webpack_exports__AnimatedCollapse = __WEBPACK_EXTERNAL_MODULE__solid_index_js_0e5c9791__.AnimatedCollapse;
11
12
  var __webpack_exports__MotionDiv = __WEBPACK_EXTERNAL_MODULE__solid_index_js_0e5c9791__.MotionDiv;
13
+ var __webpack_exports__Presence = __WEBPACK_EXTERNAL_MODULE__solid_index_js_0e5c9791__.Presence;
14
+ var __webpack_exports__computeCollapseStyle = __WEBPACK_EXTERNAL_MODULE__solid_index_js_0e5c9791__.computeCollapseStyle;
12
15
  var __webpack_exports__createMotionPresets = __WEBPACK_EXTERNAL_MODULE__presets_js_17a1eb8d__.createMotionPresets;
13
16
  var __webpack_exports__createMotionSystem = __WEBPACK_EXTERNAL_MODULE__system_js_50c29608__.createMotionSystem;
14
17
  var __webpack_exports__createPopmotionDriver = __WEBPACK_EXTERNAL_MODULE__popmotion_js_a3c50ca9__.createPopmotionDriver;
@@ -23,6 +26,8 @@ var __webpack_exports__motionDistances = __WEBPACK_EXTERNAL_MODULE__tokens_js_af
23
26
  var __webpack_exports__motionDurations = __WEBPACK_EXTERNAL_MODULE__tokens_js_afbe9ddb__.motionDurations;
24
27
  var __webpack_exports__motionEasings = __WEBPACK_EXTERNAL_MODULE__tokens_js_afbe9ddb__.motionEasings;
25
28
  var __webpack_exports__motionPresets = __WEBPACK_EXTERNAL_MODULE__presets_js_17a1eb8d__.motionPresets;
29
+ var __webpack_exports__nextCollapsePhase = __WEBPACK_EXTERNAL_MODULE__solid_index_js_0e5c9791__.nextCollapsePhase;
30
+ var __webpack_exports__nextPresenceState = __WEBPACK_EXTERNAL_MODULE__solid_index_js_0e5c9791__.nextPresenceState;
26
31
  var __webpack_exports__noMotion = __WEBPACK_EXTERNAL_MODULE__presets_js_17a1eb8d__.noMotion;
27
32
  var __webpack_exports__prefersReducedMotion = __WEBPACK_EXTERNAL_MODULE__reduced_motion_js_6b898224__.prefersReducedMotion;
28
33
  var __webpack_exports__registerPreset = __WEBPACK_EXTERNAL_MODULE__presets_js_17a1eb8d__.registerPreset;
@@ -31,4 +36,4 @@ var __webpack_exports__resolvePreset = __WEBPACK_EXTERNAL_MODULE__presets_js_17a
31
36
  var __webpack_exports__routeTransition = __WEBPACK_EXTERNAL_MODULE__presets_js_17a1eb8d__.routeTransition;
32
37
  var __webpack_exports__runMotion = __WEBPACK_EXTERNAL_MODULE__engine_js_45c545c3__.runMotion;
33
38
  var __webpack_exports__setMotionDriver = __WEBPACK_EXTERNAL_MODULE__driver_js_09718513__.setMotionDriver;
34
- export { __webpack_exports__MotionDiv as MotionDiv, __webpack_exports__createMotionPresets as createMotionPresets, __webpack_exports__createMotionSystem as createMotionSystem, __webpack_exports__createPopmotionDriver as createPopmotionDriver, __webpack_exports__createRouteTransitionResolver as createRouteTransitionResolver, __webpack_exports__defaultMotionTokens as defaultMotionTokens, __webpack_exports__enablePopmotion as enablePopmotion, __webpack_exports__getMotionDriver as getMotionDriver, __webpack_exports__getPreset as getPreset, __webpack_exports__immediateDriver as immediateDriver, __webpack_exports__mergeMotionTokens as mergeMotionTokens, __webpack_exports__motionDistances as motionDistances, __webpack_exports__motionDurations as motionDurations, __webpack_exports__motionEasings as motionEasings, __webpack_exports__motionPresets as motionPresets, __webpack_exports__noMotion as noMotion, __webpack_exports__prefersReducedMotion as prefersReducedMotion, __webpack_exports__registerPreset as registerPreset, __webpack_exports__resolveEase as resolveEase, __webpack_exports__resolvePreset as resolvePreset, __webpack_exports__routeTransition as routeTransition, __webpack_exports__runMotion as runMotion, __webpack_exports__setMotionDriver as setMotionDriver };
39
+ export { __webpack_exports__AnimatedCollapse as AnimatedCollapse, __webpack_exports__MotionDiv as MotionDiv, __webpack_exports__Presence as Presence, __webpack_exports__computeCollapseStyle as computeCollapseStyle, __webpack_exports__createMotionPresets as createMotionPresets, __webpack_exports__createMotionSystem as createMotionSystem, __webpack_exports__createPopmotionDriver as createPopmotionDriver, __webpack_exports__createRouteTransitionResolver as createRouteTransitionResolver, __webpack_exports__defaultMotionTokens as defaultMotionTokens, __webpack_exports__enablePopmotion as enablePopmotion, __webpack_exports__getMotionDriver as getMotionDriver, __webpack_exports__getPreset as getPreset, __webpack_exports__immediateDriver as immediateDriver, __webpack_exports__mergeMotionTokens as mergeMotionTokens, __webpack_exports__motionDistances as motionDistances, __webpack_exports__motionDurations as motionDurations, __webpack_exports__motionEasings as motionEasings, __webpack_exports__motionPresets as motionPresets, __webpack_exports__nextCollapsePhase as nextCollapsePhase, __webpack_exports__nextPresenceState as nextPresenceState, __webpack_exports__noMotion as noMotion, __webpack_exports__prefersReducedMotion as prefersReducedMotion, __webpack_exports__registerPreset as registerPreset, __webpack_exports__resolveEase as resolveEase, __webpack_exports__resolvePreset as resolvePreset, __webpack_exports__routeTransition as routeTransition, __webpack_exports__runMotion as runMotion, __webpack_exports__setMotionDriver as setMotionDriver };
@@ -0,0 +1,35 @@
1
+ import { type JSX } from "solid-js";
2
+ export interface AnimatedCollapseProps {
3
+ /** Whether the panel is expanded. */
4
+ open: boolean;
5
+ children: JSX.Element;
6
+ /** Animation duration in seconds. Default 0.24. */
7
+ duration?: number;
8
+ /** Wrapper class (applied to the height-animated container). */
9
+ class?: string;
10
+ /** Inner content class (applied to the measured content wrapper). */
11
+ contentClass?: string;
12
+ /** Cross-fade content during open/close. Default true. */
13
+ animateOpacity?: boolean;
14
+ /** Remove content from the tree when fully closed. Default false. */
15
+ unmountOnExit?: boolean;
16
+ /** Forwarded to the wrapper element. */
17
+ id?: string;
18
+ /** Override for prefers-reduced-motion detection. */
19
+ reduceMotion?: boolean;
20
+ }
21
+ type CollapsePhase = "closed" | "opening" | "open" | "closing";
22
+ /**
23
+ * Pure: returns the next collapse phase given the previous phase and target
24
+ * `open`. Exposed for unit testing.
25
+ */
26
+ export declare const nextCollapsePhase: (prev: CollapsePhase, open: boolean) => CollapsePhase;
27
+ /**
28
+ * Pure: computes the inline style for the collapse wrapper based on phase,
29
+ * measured height (px), and opacity preference. `null` means "no inline
30
+ * height — let layout flow" (used while fully open with dynamic content).
31
+ * Exposed for unit testing.
32
+ */
33
+ export declare const computeCollapseStyle: (phase: CollapsePhase, heightPx: number | null, animateOpacity: boolean) => JSX.CSSProperties;
34
+ export declare const AnimatedCollapse: (props: AnimatedCollapseProps) => JSX.Element;
35
+ export default AnimatedCollapse;
@@ -0,0 +1,166 @@
1
+ import * as __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__ from "solid-js/web";
2
+ import * as __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__ from "solid-js";
3
+ import * as __WEBPACK_EXTERNAL_MODULE__driver_js_6225697c__ from "../driver.js";
4
+ import * as __WEBPACK_EXTERNAL_MODULE__easing_js_1a315be3__ from "../easing.js";
5
+ import * as __WEBPACK_EXTERNAL_MODULE__reduced_motion_js_a60363ae__ from "../reduced-motion.js";
6
+ var _tmpl$ = /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.template)("<div><div>");
7
+ const nextCollapsePhase = (prev, open)=>{
8
+ if (open) return "open" === prev || "opening" === prev ? prev : "opening";
9
+ return "closed" === prev || "closing" === prev ? prev : "closing";
10
+ };
11
+ const computeCollapseStyle = (phase, heightPx, animateOpacity)=>{
12
+ const style = {
13
+ overflow: "hidden"
14
+ };
15
+ if ("closed" === phase) {
16
+ style.height = "0px";
17
+ if (animateOpacity) style.opacity = 0;
18
+ return style;
19
+ }
20
+ if ("open" === phase) {
21
+ if (animateOpacity) style.opacity = 1;
22
+ style.overflow = "visible";
23
+ return style;
24
+ }
25
+ if (null !== heightPx) style.height = `${heightPx}px`;
26
+ return style;
27
+ };
28
+ const DEFAULT_DURATION = 0.24;
29
+ const AnimatedCollapse = (props)=>{
30
+ const [phase, setPhase] = (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.createSignal)(props.open ? "open" : "closed");
31
+ const [heightPx, setHeightPx] = (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.createSignal)(props.open ? null : 0);
32
+ const [opacity, setOpacity] = (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.createSignal)(props.open ? 1 : 0);
33
+ let contentEl;
34
+ let activeControl = null;
35
+ let resizeObserver = null;
36
+ const stopActive = ()=>{
37
+ activeControl?.stop();
38
+ activeControl = null;
39
+ };
40
+ const measure = ()=>{
41
+ if (!contentEl) return 0;
42
+ return contentEl.scrollHeight;
43
+ };
44
+ const animateOpacity = ()=>false !== props.animateOpacity;
45
+ const setupObserver = ()=>{
46
+ if ("undefined" == typeof ResizeObserver) return;
47
+ if (!contentEl || resizeObserver) return;
48
+ resizeObserver = new ResizeObserver(()=>{});
49
+ resizeObserver.observe(contentEl);
50
+ };
51
+ const teardownObserver = ()=>{
52
+ resizeObserver?.disconnect();
53
+ resizeObserver = null;
54
+ };
55
+ const runAnimation = (target, fromHeight, toHeight)=>{
56
+ stopActive();
57
+ const reduce = props.reduceMotion ?? (0, __WEBPACK_EXTERNAL_MODULE__reduced_motion_js_a60363ae__.prefersReducedMotion)();
58
+ if (reduce) {
59
+ setHeightPx(toHeight);
60
+ if (animateOpacity()) setOpacity("opening" === target ? 1 : 0);
61
+ finish(target);
62
+ return;
63
+ }
64
+ const duration = (props.duration ?? DEFAULT_DURATION) * 1000;
65
+ const ease = (0, __WEBPACK_EXTERNAL_MODULE__easing_js_1a315be3__.resolveEase)("ease-out");
66
+ const driver = (0, __WEBPACK_EXTERNAL_MODULE__driver_js_6225697c__.getMotionDriver)();
67
+ const heightControl = driver({
68
+ from: fromHeight,
69
+ to: toHeight,
70
+ duration,
71
+ ease,
72
+ onUpdate: (value)=>setHeightPx(value),
73
+ onComplete: ()=>finish(target)
74
+ });
75
+ if (animateOpacity()) {
76
+ const fromOpacity = "opening" === target ? 0 : 1;
77
+ const toOpacity = "opening" === target ? 1 : 0;
78
+ const opacityControl = driver({
79
+ from: fromOpacity,
80
+ to: toOpacity,
81
+ duration,
82
+ ease,
83
+ onUpdate: (value)=>setOpacity(value)
84
+ });
85
+ activeControl = {
86
+ stop: ()=>{
87
+ heightControl.stop();
88
+ opacityControl.stop();
89
+ }
90
+ };
91
+ } else {
92
+ setOpacity(1);
93
+ activeControl = heightControl;
94
+ }
95
+ };
96
+ const finish = (target)=>{
97
+ if ("opening" === target) {
98
+ setPhase("open");
99
+ setHeightPx(null);
100
+ if (animateOpacity()) setOpacity(1);
101
+ } else if ("closing" === target) {
102
+ setPhase("closed");
103
+ setHeightPx(0);
104
+ if (animateOpacity()) setOpacity(0);
105
+ teardownObserver();
106
+ }
107
+ };
108
+ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.createEffect)(()=>{
109
+ const open = props.open;
110
+ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.untrack)(()=>{
111
+ const target = nextCollapsePhase(phase(), open);
112
+ if (target === phase()) return;
113
+ setPhase(target);
114
+ if ("opening" === target) requestAnimationFrame(()=>{
115
+ const to = measure();
116
+ setupObserver();
117
+ runAnimation("opening", 0, to);
118
+ });
119
+ else if ("closing" === target) {
120
+ const from = measure();
121
+ setHeightPx(from);
122
+ requestAnimationFrame(()=>runAnimation("closing", from, 0));
123
+ }
124
+ });
125
+ });
126
+ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.onCleanup)(()=>{
127
+ stopActive();
128
+ teardownObserver();
129
+ });
130
+ const shouldRender = ()=>props.unmountOnExit ? "closed" !== phase() : true;
131
+ const wrapperStyle = ()=>computeCollapseStyle(phase(), heightPx(), animateOpacity());
132
+ return (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.createComponent)(__WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.Show, {
133
+ get when () {
134
+ return shouldRender();
135
+ },
136
+ get children () {
137
+ var _el$ = _tmpl$(), _el$2 = _el$.firstChild;
138
+ var _ref$ = contentEl;
139
+ "function" == typeof _ref$ ? (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.use)(_ref$, _el$2) : contentEl = _el$2;
140
+ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.insert)(_el$2, ()=>props.children);
141
+ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.effect)((_p$)=>{
142
+ var _v$ = props.id, _v$2 = props.class, _v$3 = {
143
+ ...wrapperStyle(),
144
+ ...animateOpacity() && "open" !== phase() ? {
145
+ opacity: opacity()
146
+ } : {}
147
+ }, _v$4 = "closed" === phase() ? true : void 0, _v$5 = props.contentClass;
148
+ _v$ !== _p$.e && (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.setAttribute)(_el$, "id", _p$.e = _v$);
149
+ _v$2 !== _p$.t && (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.className)(_el$, _p$.t = _v$2);
150
+ _p$.a = (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.style)(_el$, _v$3, _p$.a);
151
+ _v$4 !== _p$.o && (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.setAttribute)(_el$, "aria-hidden", _p$.o = _v$4);
152
+ _v$5 !== _p$.i && (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.className)(_el$2, _p$.i = _v$5);
153
+ return _p$;
154
+ }, {
155
+ e: void 0,
156
+ t: void 0,
157
+ a: void 0,
158
+ o: void 0,
159
+ i: void 0
160
+ });
161
+ return _el$;
162
+ }
163
+ });
164
+ };
165
+ const solid_AnimatedCollapse = AnimatedCollapse;
166
+ export { AnimatedCollapse, computeCollapseStyle, solid_AnimatedCollapse as default, nextCollapsePhase };
@@ -0,0 +1,30 @@
1
+ import { type JSX } from "solid-js";
2
+ export type PresenceRenderProp = (isExiting: () => boolean, onExitComplete: () => void) => JSX.Element;
3
+ export interface PresenceProps {
4
+ /** Controls whether the child should be mounted/visible. */
5
+ when: boolean;
6
+ /**
7
+ * Render function. Receives an `isExiting` accessor (pass through to
8
+ * MotionDiv's `isExiting`) and an `onExitComplete` callback that must be
9
+ * wired to MotionDiv (or invoked manually when the exit animation ends).
10
+ */
11
+ children: PresenceRenderProp;
12
+ /**
13
+ * Fallback timeout (ms) after which Presence force-unmounts the child if
14
+ * `onExitComplete` was never called. Prevents stuck-exit states. Default 800.
15
+ */
16
+ exitTimeout?: number;
17
+ /** Override for prefers-reduced-motion detection. */
18
+ reduceMotion?: boolean;
19
+ }
20
+ interface PresenceState {
21
+ mounted: boolean;
22
+ isExiting: boolean;
23
+ }
24
+ /**
25
+ * Pure state transition for Presence. Given the previous state and the next
26
+ * `when` value, returns the next state. Exposed for unit testing.
27
+ */
28
+ export declare const nextPresenceState: (prev: PresenceState, when: boolean) => PresenceState;
29
+ export declare const Presence: (props: PresenceProps) => JSX.Element;
30
+ export default Presence;
@@ -0,0 +1,65 @@
1
+ import * as __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__ from "solid-js/web";
2
+ import * as __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__ from "solid-js";
3
+ import * as __WEBPACK_EXTERNAL_MODULE__reduced_motion_js_a60363ae__ from "../reduced-motion.js";
4
+ const nextPresenceState = (prev, when)=>{
5
+ if (when) return {
6
+ mounted: true,
7
+ isExiting: false
8
+ };
9
+ if (prev.mounted && !prev.isExiting) return {
10
+ mounted: true,
11
+ isExiting: true
12
+ };
13
+ return prev.mounted ? prev : {
14
+ mounted: false,
15
+ isExiting: false
16
+ };
17
+ };
18
+ const DEFAULT_EXIT_TIMEOUT = 800;
19
+ const Presence_Presence = (props)=>{
20
+ const [state, setState] = (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.createSignal)({
21
+ mounted: props.when,
22
+ isExiting: false
23
+ });
24
+ let exitTimer = null;
25
+ const clearTimer = ()=>{
26
+ if (null !== exitTimer) {
27
+ clearTimeout(exitTimer);
28
+ exitTimer = null;
29
+ }
30
+ };
31
+ const finishExit = ()=>{
32
+ clearTimer();
33
+ setState((prev)=>prev.isExiting ? {
34
+ mounted: false,
35
+ isExiting: false
36
+ } : prev);
37
+ };
38
+ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.createEffect)(()=>{
39
+ const when = props.when;
40
+ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.untrack)(()=>{
41
+ const next = nextPresenceState(state(), when);
42
+ if (next === state()) return;
43
+ setState(next);
44
+ if (next.isExiting) {
45
+ const reduce = props.reduceMotion ?? (0, __WEBPACK_EXTERNAL_MODULE__reduced_motion_js_a60363ae__.prefersReducedMotion)();
46
+ if (reduce) return void queueMicrotask(finishExit);
47
+ clearTimer();
48
+ const ms = props.exitTimeout ?? DEFAULT_EXIT_TIMEOUT;
49
+ exitTimer = setTimeout(finishExit, ms);
50
+ } else clearTimer();
51
+ });
52
+ });
53
+ (0, __WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.onCleanup)(clearTimer);
54
+ const isExiting = ()=>state().isExiting;
55
+ return (0, __WEBPACK_EXTERNAL_MODULE_solid_js_web_35d951b7__.createComponent)(__WEBPACK_EXTERNAL_MODULE_solid_js_aeefcc6d__.Show, {
56
+ get when () {
57
+ return state().mounted;
58
+ },
59
+ get children () {
60
+ return props.children(isExiting, finishExit);
61
+ }
62
+ });
63
+ };
64
+ const Presence = Presence_Presence;
65
+ export { Presence_Presence as Presence, Presence as default, nextPresenceState };
@@ -1,2 +1,6 @@
1
1
  export { default as MotionDiv } from "./MotionDiv";
2
2
  export type { MotionDivProps } from "./MotionDiv";
3
+ export { default as Presence, nextPresenceState } from "./Presence";
4
+ export type { PresenceProps, PresenceRenderProp } from "./Presence";
5
+ export { default as AnimatedCollapse, nextCollapsePhase, computeCollapseStyle, } from "./AnimatedCollapse";
6
+ export type { AnimatedCollapseProps } from "./AnimatedCollapse";
@@ -1,3 +1,10 @@
1
1
  import * as __WEBPACK_EXTERNAL_MODULE__MotionDiv_js_142518a8__ from "./MotionDiv.js";
2
+ import * as __WEBPACK_EXTERNAL_MODULE__Presence_js_c85f5127__ from "./Presence.js";
3
+ import * as __WEBPACK_EXTERNAL_MODULE__AnimatedCollapse_js_e9eaa465__ from "./AnimatedCollapse.js";
4
+ var __webpack_exports__AnimatedCollapse = __WEBPACK_EXTERNAL_MODULE__AnimatedCollapse_js_e9eaa465__["default"];
2
5
  var __webpack_exports__MotionDiv = __WEBPACK_EXTERNAL_MODULE__MotionDiv_js_142518a8__["default"];
3
- export { __webpack_exports__MotionDiv as MotionDiv };
6
+ var __webpack_exports__Presence = __WEBPACK_EXTERNAL_MODULE__Presence_js_c85f5127__["default"];
7
+ var __webpack_exports__computeCollapseStyle = __WEBPACK_EXTERNAL_MODULE__AnimatedCollapse_js_e9eaa465__.computeCollapseStyle;
8
+ var __webpack_exports__nextCollapsePhase = __WEBPACK_EXTERNAL_MODULE__AnimatedCollapse_js_e9eaa465__.nextCollapsePhase;
9
+ var __webpack_exports__nextPresenceState = __WEBPACK_EXTERNAL_MODULE__Presence_js_c85f5127__.nextPresenceState;
10
+ export { __webpack_exports__AnimatedCollapse as AnimatedCollapse, __webpack_exports__MotionDiv as MotionDiv, __webpack_exports__Presence as Presence, __webpack_exports__computeCollapseStyle as computeCollapseStyle, __webpack_exports__nextCollapsePhase as nextCollapsePhase, __webpack_exports__nextPresenceState as nextPresenceState };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pathscale/ui",
3
- "version": "1.1.78",
3
+ "version": "1.1.80",
4
4
  "author": "pathscale",
5
5
  "repository": {
6
6
  "type": "git",