@jsenv/navi 0.16.51 → 0.16.52

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.
@@ -4570,54 +4570,6 @@ const isProps = (value) => {
4570
4570
  return value !== null && typeof value === "object";
4571
4571
  };
4572
4572
 
4573
- /**
4574
- * Creates a signal that stays synchronized with an external value,
4575
- * only updating the signal when the value actually changes.
4576
- *
4577
- * This hook solves a common reactive UI pattern where:
4578
- * 1. A signal controls a UI element (like an input field)
4579
- * 2. The UI element can be modified by user interaction
4580
- * 3. When the external "source of truth" changes, it should take precedence
4581
- *
4582
- * @param {any} value - The external value to sync with (the "source of truth")
4583
- * @param {any} [initialValue] - Optional initial value for the signal (defaults to value)
4584
- * @returns {Signal} A signal that tracks the external value but allows temporary local changes
4585
- *
4586
- * @example
4587
- * const FileNameEditor = ({ file }) => {
4588
- * // Signal stays in sync with file.name, but allows user editing
4589
- * const nameSignal = useSignalSync(file.name);
4590
- *
4591
- * return (
4592
- * <Editable
4593
- * valueSignal={nameSignal} // User can edit this
4594
- * action={renameFileAction} // Saves changes
4595
- * />
4596
- * );
4597
- * };
4598
- *
4599
- * // Scenario:
4600
- * // 1. file.name = "doc.txt", nameSignal.value = "doc.txt"
4601
- * // 2. User types "report" -> nameSignal.value = "report.txt"
4602
- * // 3. External update: file.name = "shared-doc.txt"
4603
- * // 4. Next render: nameSignal.value = "shared-doc.txt" (model wins!)
4604
- *
4605
- */
4606
-
4607
- const useSignalSync = (value, initialValue = value) => {
4608
- const signal = useSignal(initialValue);
4609
- const previousValueRef = useRef(value);
4610
-
4611
- // Only update signal when external value actually changes
4612
- // This preserves user input between external changes
4613
- if (previousValueRef.current !== value) {
4614
- previousValueRef.current = value;
4615
- signal.value = value; // Model takes precedence
4616
- }
4617
-
4618
- return signal;
4619
- };
4620
-
4621
4573
  const addIntoArray = (array, ...valuesToAdd) => {
4622
4574
  if (valuesToAdd.length === 1) {
4623
4575
  const [valueToAdd] = valuesToAdd;
@@ -4680,6 +4632,69 @@ const removeFromArray = (array, ...valuesToRemove) => {
4680
4632
  return hasRemovedValues ? arrayWithoutTheseValues : array;
4681
4633
  };
4682
4634
 
4635
+ const useArraySignalMembership = (arraySignal, id) => {
4636
+ const array = arraySignal.value;
4637
+ const found = array.includes(id);
4638
+ return [
4639
+ found,
4640
+ (enabled) => {
4641
+ if (enabled) {
4642
+ arraySignal.value = addIntoArray(array, id);
4643
+ } else {
4644
+ arraySignal.value = removeFromArray(array, id);
4645
+ }
4646
+ },
4647
+ ];
4648
+ };
4649
+
4650
+ /**
4651
+ * Creates a signal that stays synchronized with an external value,
4652
+ * only updating the signal when the value actually changes.
4653
+ *
4654
+ * This hook solves a common reactive UI pattern where:
4655
+ * 1. A signal controls a UI element (like an input field)
4656
+ * 2. The UI element can be modified by user interaction
4657
+ * 3. When the external "source of truth" changes, it should take precedence
4658
+ *
4659
+ * @param {any} value - The external value to sync with (the "source of truth")
4660
+ * @param {any} [initialValue] - Optional initial value for the signal (defaults to value)
4661
+ * @returns {Signal} A signal that tracks the external value but allows temporary local changes
4662
+ *
4663
+ * @example
4664
+ * const FileNameEditor = ({ file }) => {
4665
+ * // Signal stays in sync with file.name, but allows user editing
4666
+ * const nameSignal = useSignalSync(file.name);
4667
+ *
4668
+ * return (
4669
+ * <Editable
4670
+ * valueSignal={nameSignal} // User can edit this
4671
+ * action={renameFileAction} // Saves changes
4672
+ * />
4673
+ * );
4674
+ * };
4675
+ *
4676
+ * // Scenario:
4677
+ * // 1. file.name = "doc.txt", nameSignal.value = "doc.txt"
4678
+ * // 2. User types "report" -> nameSignal.value = "report.txt"
4679
+ * // 3. External update: file.name = "shared-doc.txt"
4680
+ * // 4. Next render: nameSignal.value = "shared-doc.txt" (model wins!)
4681
+ *
4682
+ */
4683
+
4684
+ const useSignalSync = (value, initialValue = value) => {
4685
+ const signal = useSignal(initialValue);
4686
+ const previousValueRef = useRef(value);
4687
+
4688
+ // Only update signal when external value actually changes
4689
+ // This preserves user input between external changes
4690
+ if (previousValueRef.current !== value) {
4691
+ previousValueRef.current = value;
4692
+ signal.value = value; // Model takes precedence
4693
+ }
4694
+
4695
+ return signal;
4696
+ };
4697
+
4683
4698
  /**
4684
4699
  * Picks the best initial value from three options using a simple priority system.
4685
4700
  *
@@ -28509,5 +28524,5 @@ const UserSvg = () => jsx("svg", {
28509
28524
  })
28510
28525
  });
28511
28526
 
28512
- export { ActionRenderer, ActiveKeyboardShortcuts, Address, BadgeCount, Box, Button, ButtonCopyToClipboard, Caption, CheckSvg, Checkbox, CheckboxList, Code, Col, Colgroup, ConstructionSvg, Details, DialogLayout, Editable, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Form, Group, HeartSvg, HomeSvg, Icon, Image, Input, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, MessageBox, Paragraph, Radio, RadioList, Route, RouteLink, Routes, RowNumberCol, RowNumberTableCell, SINGLE_SPACE_CONSTRAINT, SVGMaskOverlay, SearchSvg, Select, SelectionContext, Separator, SettingsSvg, StarSvg, SummaryMarker, Svg, Tab, TabList, Table, TableCell, Tbody, Text, Thead, Title, Tr, UITransition, UserSvg, ViewportLayout, actionIntegratedVia, addCustomMessage, clearAllRoutes, compareTwoJsValues, createAction, createAvailableConstraint, createRequestCanceller, createSelectionKeyboardShortcuts, enableDebugActions, enableDebugOnDocumentLoading, forwardActionRequested, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, localStorageSignal, navBack, navForward, navTo, openCallout, rawUrlPart, reload, removeCustomMessage, requestAction, rerunActions, resource, setBaseUrl, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, updateActions, useActionData, useActionStatus, useCalloutClose, useCellsAndColumns, useConstraintValidityState, useDependenciesDiff, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useMatchingRouteInfo, useNavState$1 as useNavState, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSignalSync, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage };
28527
+ export { ActionRenderer, ActiveKeyboardShortcuts, Address, BadgeCount, Box, Button, ButtonCopyToClipboard, Caption, CheckSvg, Checkbox, CheckboxList, Code, Col, Colgroup, ConstructionSvg, Details, DialogLayout, Editable, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Form, Group, HeartSvg, HomeSvg, Icon, Image, Input, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, MessageBox, Paragraph, Radio, RadioList, Route, RouteLink, Routes, RowNumberCol, RowNumberTableCell, SINGLE_SPACE_CONSTRAINT, SVGMaskOverlay, SearchSvg, Select, SelectionContext, Separator, SettingsSvg, StarSvg, SummaryMarker, Svg, Tab, TabList, Table, TableCell, Tbody, Text, Thead, Title, Tr, UITransition, UserSvg, ViewportLayout, actionIntegratedVia, addCustomMessage, clearAllRoutes, compareTwoJsValues, createAction, createAvailableConstraint, createRequestCanceller, createSelectionKeyboardShortcuts, enableDebugActions, enableDebugOnDocumentLoading, forwardActionRequested, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, localStorageSignal, navBack, navForward, navTo, openCallout, rawUrlPart, reload, removeCustomMessage, requestAction, rerunActions, resource, setBaseUrl, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, updateActions, useActionData, useActionStatus, useArraySignalMembership, useCalloutClose, useCellsAndColumns, useConstraintValidityState, useDependenciesDiff, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useMatchingRouteInfo, useNavState$1 as useNavState, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSignalSync, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage };
28513
28528
  //# sourceMappingURL=jsenv_navi.js.map