@jsenv/navi 0.26.42 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import { isValidElement, createContext, h, toChildArray, render, Fragment, clone
3
3
  import { useErrorBoundary, useLayoutEffect, useEffect, useContext, useMemo, useRef, useState, useCallback, useId } from "preact/hooks";
4
4
  import { jsxs, jsx, Fragment as Fragment$1 } from "preact/jsx-runtime";
5
5
  import { signal, effect, computed, batch, useSignal } from "@preact/signals";
6
- import { createIterableWeakSet, createEventGroupLogger, mergeOneStyle, normalizeStyle, createPubSub, dispatchInternalCustomEvent, getElementSignature, findEvent, mergeTwoStyles, normalizeStyles, createGroupTransitionController, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, findBefore, findAfter, createValueEffect, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, dispatchPublicCustomEvent, resolveCSSColor, createStyleController, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, measureLongestVisualLineWidth, findFocusDelegateTarget, getKeyboardEventDefaultAction, resolveCSSSize, activeElementSignal, hasCSSSizeUnit, resolveOklchLightness, contrastColor, dispatchCustomEvent, initFocusGroup, elementIsFocusable, findFocusable, trapScrollInside, trapFocusInside, snapToPixel, scrollIntoViewScoped, dragAfterThreshold, getScrollContainer, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement, measureWidestChildRow } from "@jsenv/dom";
6
+ import { createIterableWeakSet, createEventGroupLogger, mergeOneStyle, normalizeStyle, createPubSub, findEvent, dispatchInternalCustomEvent, getElementSignature, mergeTwoStyles, normalizeStyles, createGroupTransitionController, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, findBefore, findAfter, createValueEffect, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, dispatchPublicCustomEvent, resolveCSSColor, createStyleController, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, measureLongestVisualLineWidth, findFocusDelegateTarget, getKeyboardEventDefaultAction, resolveCSSSize, activeElementSignal, hasCSSSizeUnit, resolveOklchLightness, contrastColor, dispatchCustomEvent, initFocusGroup, elementIsFocusable, findFocusable, trapScrollInside, trapFocusInside, snapToPixel, scrollIntoViewScoped, dragAfterThreshold, getScrollContainer, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement, measureWidestChildRow } from "@jsenv/dom";
7
7
  export { contrastColor, startDragToReorder } from "@jsenv/dom";
8
8
  import { prefixFirstAndIndentRemainingLines } from "@jsenv/humanize";
9
9
  import { createValidity } from "@jsenv/validity";
@@ -7403,9 +7403,12 @@ const addInputEffect = (
7403
7403
  };
7404
7404
 
7405
7405
  // Standard user input (typing)
7406
- input.addEventListener("input", onEvent);
7406
+ const onInput = (e) => {
7407
+ onEvent(e);
7408
+ };
7409
+ input.addEventListener("input", onInput);
7407
7410
  addTeardown(() => {
7408
- input.removeEventListener("input", onEvent);
7411
+ input.removeEventListener("input", onInput);
7409
7412
  });
7410
7413
 
7411
7414
  // Form reset - need to check the form
@@ -7424,27 +7427,28 @@ const addInputEffect = (
7424
7427
  input.removeEventListener("paste", onEvent);
7425
7428
  });
7426
7429
 
7427
- if (input.type === "radio") {
7430
+ input.addEventListener("navi_ui_state_change", (e) => {
7428
7431
  // radios are unchecked by an internal setUIState call when another radio is checked.
7429
7432
  // navi_ui_state_change is dispatched whenever setUIState changes state, so we
7430
7433
  // listen here to keep currentState in sync — otherwise input_effect thinks the
7431
7434
  // radio is still checked and ignores the next user click as "state unchanged".
7432
- input.addEventListener("navi_ui_state_change", () => {
7433
- currentState = getState();
7434
- });
7435
- }
7436
-
7437
- const onNaviClear = (e) => {
7438
- // "navi_clear" behaves like an async event
7439
- // a bit like form reset because
7440
- // our action will be updated async after the component re-renders
7441
- // and we need to wait that to happen to properly call action with the right value
7442
- debugInteraction(e, `navi_clear received, scheduling callback`);
7443
- onAsyncEvent(e, { skipDebounce: true });
7444
- };
7445
- input.addEventListener("navi_clear", onNaviClear);
7446
- addTeardown(() => {
7447
- input.removeEventListener("navi_clear", onNaviClear);
7435
+ if (input.type === "radio") {
7436
+ currentState = e.detail.value;
7437
+ }
7438
+ const clearEvent = findEvent(
7439
+ e,
7440
+ (eInChain) =>
7441
+ eInChain.type === "navi_set_ui_state" && eInChain.detail.isClear,
7442
+ );
7443
+ const isClear = Boolean(clearEvent);
7444
+ if (isClear) {
7445
+ // "navi_clear" behaves like an async event
7446
+ // a bit like form reset because
7447
+ // our action will be updated async after the component re-renders
7448
+ // and we need to wait that to happen to properly call action with the right value
7449
+ debugInteraction(e, `navi_clear received, scheduling callback`);
7450
+ onAsyncEvent(e, { skipDebounce: true });
7451
+ }
7448
7452
  });
7449
7453
 
7450
7454
  return teardown;
@@ -24995,6 +24999,9 @@ const routeArgs = (args, { event, action, other }) => {
24995
24999
  return other(...args);
24996
25000
  };
24997
25001
 
25002
+ const triggerStringAction = (actionName, event) => {
25003
+ return resolveActionProp(actionName)(event);
25004
+ };
24998
25005
  const resolveActionProp = (action) => {
24999
25006
  if (typeof action === "string") {
25000
25007
  const naviAction = STRING_ACTIONS[action];
@@ -25103,12 +25110,12 @@ const update = createUICallback({
25103
25110
  return requestUpdate(event, value);
25104
25111
  },
25105
25112
  });
25106
- const requestUpdate = (event, value) => {
25113
+ const requestUpdate = (event, value, { isClear } = {}) => {
25107
25114
  const actionTarget = getActionTarget(event);
25108
25115
  if (!actionTarget) {
25109
25116
  return false;
25110
25117
  }
25111
- return dispatchRequestSetUIState(actionTarget, value, { event });
25118
+ return dispatchRequestSetUIState(actionTarget, value, { event, isClear });
25112
25119
  };
25113
25120
 
25114
25121
  /**
@@ -25192,12 +25199,20 @@ const requestClosestAction = (event) => {
25192
25199
  const clear = createUICallback({
25193
25200
  name: "clear",
25194
25201
  event: (event) => {
25195
- update("", { event });
25196
- return requestClose(event);
25202
+ requestUpdate(event, "", { isClear: true });
25203
+ const expandableEl = event.currentTarget.closest("[aria-expanded]");
25204
+ if (expandableEl) {
25205
+ return requestClose(event);
25206
+ }
25207
+ return true;
25197
25208
  },
25198
25209
  action: (v, { event }) => {
25199
- update("", { event });
25200
- return requestClose(event);
25210
+ requestUpdate(event, "", { isClear: true });
25211
+ const expandableEl = event.currentTarget.closest("[aria-expanded]");
25212
+ if (expandableEl) {
25213
+ return requestClose(event);
25214
+ }
25215
+ return true;
25201
25216
  },
25202
25217
  });
25203
25218
  /**
@@ -25227,13 +25242,13 @@ const close = createUICallback({
25227
25242
  const cancel = createUICallback({
25228
25243
  name: "cancel",
25229
25244
  event: (event) => {
25230
- return requestClose(event, { cancel: true });
25245
+ return requestClose(event, { isCancel: true });
25231
25246
  },
25232
25247
  action: (_, { event }) => {
25233
- return requestClose(event, { cancel: true });
25248
+ return requestClose(event, { isCancel: true });
25234
25249
  },
25235
25250
  });
25236
- const requestClose = (event, { cancel = false } = {}) => {
25251
+ const requestClose = (event, { isCancel = false } = {}) => {
25237
25252
  const currentTarget = event.currentTarget;
25238
25253
  const expandableEl = currentTarget.closest("[aria-expanded]");
25239
25254
  if (!expandableEl) {
@@ -25245,7 +25260,7 @@ const requestClose = (event, { cancel = false } = {}) => {
25245
25260
  }
25246
25261
  return dispatchCustomEvent(expandableEl, "navi_request_close", {
25247
25262
  event,
25248
- cancel,
25263
+ isCancel,
25249
25264
  });
25250
25265
  };
25251
25266
 
@@ -25612,7 +25627,7 @@ const useControlProps = (props, {
25612
25627
  name: "navi_change",
25613
25628
  callback: asAction
25614
25629
  };
25615
- enterEffect = e => resolveActionProp("send")(e);
25630
+ enterEffect = e => triggerStringAction("send", e);
25616
25631
  if (picker) {
25617
25632
  mousedownInteraction = {
25618
25633
  name: "mousedown to open picker",
@@ -29199,38 +29214,45 @@ const NAVI_NUMBER_TYPE_DEFAULTS = {
29199
29214
  navi_percentage: { type: "number", min: 0, max: 100, step: 1 },
29200
29215
  };
29201
29216
 
29202
- const toInputDate = (value) => {
29217
+ const normalizeToDate = (value) => {
29203
29218
  if (value === undefined || value === null) {
29219
+ return null;
29220
+ }
29221
+ if (typeof value === "number") {
29222
+ return new Date(value);
29223
+ }
29224
+ if (value instanceof Date) {
29204
29225
  return value;
29205
29226
  }
29206
- if (!(value instanceof Date)) {
29227
+ return null;
29228
+ };
29229
+
29230
+ const toInputDate = (value) => {
29231
+ const date = normalizeToDate(value);
29232
+ if (!date) {
29207
29233
  return value;
29208
29234
  }
29209
- const yyyy = value.getFullYear();
29210
- const mm = String(value.getMonth() + 1).padStart(2, "0");
29211
- const dd = String(value.getDate()).padStart(2, "0");
29235
+ const yyyy = date.getFullYear();
29236
+ const mm = String(date.getMonth() + 1).padStart(2, "0");
29237
+ const dd = String(date.getDate()).padStart(2, "0");
29212
29238
  return `${yyyy}-${mm}-${dd}`;
29213
29239
  };
29214
29240
  const toInputMonth = (value) => {
29215
- if (value === undefined || value === null) {
29216
- return value;
29217
- }
29218
- if (!(value instanceof Date)) {
29241
+ const date = normalizeToDate(value);
29242
+ if (!date) {
29219
29243
  return value;
29220
29244
  }
29221
- const yyyy = value.getFullYear();
29222
- const mm = String(value.getMonth() + 1).padStart(2, "0");
29245
+ const yyyy = date.getFullYear();
29246
+ const mm = String(date.getMonth() + 1).padStart(2, "0");
29223
29247
  return `${yyyy}-${mm}`;
29224
29248
  };
29225
29249
  const toInputWeek = (value) => {
29226
- if (value === undefined || value === null) {
29227
- return value;
29228
- }
29229
- if (!(value instanceof Date)) {
29250
+ const date = normalizeToDate(value);
29251
+ if (!date) {
29230
29252
  return value;
29231
29253
  }
29232
29254
  // ISO week number
29233
- const d = new Date(value);
29255
+ const d = new Date(date);
29234
29256
  d.setHours(0, 0, 0, 0);
29235
29257
  d.setDate(d.getDate() + 3 - ((d.getDay() + 6) % 7));
29236
29258
  const yearStart = new Date(d.getFullYear(), 0, 4);
@@ -29241,28 +29263,24 @@ const toInputWeek = (value) => {
29241
29263
  return `${d.getFullYear()}-W${String(week).padStart(2, "0")}`;
29242
29264
  };
29243
29265
  const toInputTime = (value) => {
29244
- if (value === undefined || value === null) {
29245
- return value;
29246
- }
29247
- if (!(value instanceof Date)) {
29266
+ const date = normalizeToDate(value);
29267
+ if (!date) {
29248
29268
  return value;
29249
29269
  }
29250
- const hh = String(value.getHours()).padStart(2, "0");
29251
- const mm = String(value.getMinutes()).padStart(2, "0");
29270
+ const hh = String(date.getHours()).padStart(2, "0");
29271
+ const mm = String(date.getMinutes()).padStart(2, "0");
29252
29272
  return `${hh}:${mm}`;
29253
29273
  };
29254
29274
  const toInputDatetime = (value) => {
29255
- if (value === undefined || value === null) {
29275
+ const date = normalizeToDate(value);
29276
+ if (!date) {
29256
29277
  return value;
29257
29278
  }
29258
- if (!(value instanceof Date)) {
29259
- return value;
29260
- }
29261
- const yyyy = value.getFullYear();
29262
- const mm = String(value.getMonth() + 1).padStart(2, "0");
29263
- const dd = String(value.getDate()).padStart(2, "0");
29264
- const hh = String(value.getHours()).padStart(2, "0");
29265
- const min = String(value.getMinutes()).padStart(2, "0");
29279
+ const yyyy = date.getFullYear();
29280
+ const mm = String(date.getMonth() + 1).padStart(2, "0");
29281
+ const dd = String(date.getDate()).padStart(2, "0");
29282
+ const hh = String(date.getHours()).padStart(2, "0");
29283
+ const min = String(date.getMinutes()).padStart(2, "0");
29266
29284
  return `${yyyy}-${mm}-${dd}T${hh}:${min}`;
29267
29285
  };
29268
29286
 
@@ -30406,6 +30424,10 @@ const InputSearch = props => {
30406
30424
  const InputSearchUI = ({
30407
30425
  icon
30408
30426
  }) => {
30427
+ const ctx = useContext(InputNativeContext);
30428
+ const {
30429
+ id
30430
+ } = ctx;
30409
30431
  return jsxs(Fragment$1, {
30410
30432
  children: [icon === undefined && jsx(InputLeftSlot, {
30411
30433
  children: jsx(Icon, {
@@ -30414,16 +30436,12 @@ const InputSearchUI = ({
30414
30436
  })
30415
30437
  }), jsx(InputRightSlot, {
30416
30438
  hideWhileEmpty: true,
30439
+ "action-target": id,
30417
30440
  onClick: e => {
30418
30441
  const input = e.currentTarget;
30419
30442
  const allowed = dispatchRequestInteraction(input, e);
30420
30443
  if (allowed) {
30421
- dispatchRequestSetUIState(input, "", {
30422
- event: e
30423
- });
30424
- dispatchCustomEvent(input, "navi_clear", {
30425
- event: e
30426
- });
30444
+ triggerStringAction("clear", e);
30427
30445
  }
30428
30446
  },
30429
30447
  children: jsx(Icon, {
@@ -31902,7 +31920,7 @@ const PickerCustom = props => {
31902
31920
  valueAtOpenRef.current = getPickerInputUIState(ref.current);
31903
31921
  };
31904
31922
  const onClose = e => {
31905
- const cancelEvent = findEvent(e, eInChain => eInChain.type === "navi_request_close" && eInChain.detail.cancel);
31923
+ const cancelEvent = findEvent(e, eInChain => eInChain.type === "navi_request_close" && eInChain.detail.isCancel);
31906
31924
  const isCancel = Boolean(cancelEvent);
31907
31925
  expandedRef.current = false;
31908
31926
  setExpanded(false);
@@ -34660,7 +34678,7 @@ const css$l = /* css */`
34660
34678
  --x-list-outline-offset: calc(-1 * var(--list-border-width));
34661
34679
 
34662
34680
  outline-width: var(--x-list-outline-width);
34663
- outline-color: var(--x-list-outline-color);
34681
+ outline-color: var(--list-outline-color);
34664
34682
  outline-offset: var(--x-list-outline-offset);
34665
34683
 
34666
34684
  &[data-focus] {