@jsenv/navi 0.25.5 → 0.25.7

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, options, toChildArray, render, cloneE
3
3
  import { useErrorBoundary, useLayoutEffect, useEffect, useContext, useMemo, useRef, useState, useCallback, useImperativeHandle, useId } from "preact/hooks";
4
4
  import { jsxs, jsx, Fragment } from "preact/jsx-runtime";
5
5
  import { signal, effect, computed, batch, useSignal } from "@preact/signals";
6
- import { createIterableWeakSet, mergeOneStyle, stringifyStyle, createPubSub, mergeTwoStyles, normalizeStyles, createGroupTransitionController, getElementSignature, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, findBefore, findAfter, createValueEffect, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, resolveCSSColor, createStyleController, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, resolveCSSSize, canInterceptKeys, activeElementSignal, contrastColor, hasCSSSizeUnit, initFocusGroup, elementIsFocusable, resolveColorLuminance, getScrollContainer, scrollIntoViewScoped, findFocusable, trapScrollInside, trapFocusInside, dragAfterThreshold, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement } from "@jsenv/dom";
6
+ import { createIterableWeakSet, mergeOneStyle, stringifyStyle, createPubSub, mergeTwoStyles, normalizeStyles, createGroupTransitionController, getElementSignature, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, findBefore, findAfter, createValueEffect, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, resolveCSSColor, createStyleController, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, resolveCSSSize, canInterceptKeys, activeElementSignal, resolveColorLuminance, contrastColor, hasCSSSizeUnit, initFocusGroup, elementIsFocusable, getScrollContainer, scrollIntoViewScoped, findFocusable, trapScrollInside, trapFocusInside, dragAfterThreshold, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement } from "@jsenv/dom";
7
7
  export { contrastColor } from "@jsenv/dom";
8
8
  import { prefixFirstAndIndentRemainingLines } from "@jsenv/humanize";
9
9
  import { createValidity } from "@jsenv/validity";
@@ -20400,25 +20400,30 @@ const isSameKey = (browserEventKey, key) => {
20400
20400
  * should be tested instead of the element itself. Useful when the element
20401
20401
  * has a transparent background but contains a coloured child (e.g. a fill
20402
20402
  * bar inside a track).
20403
+ * @param {string} [options.colorProperty] - CSS property to read instead of
20404
+ * `background-color`. Useful for SVG elements where the color is expressed
20405
+ * as `fill` or `stroke`.
20403
20406
  */
20404
-
20405
20407
  const useDarkBackgroundAttribute = (
20406
20408
  ref,
20407
20409
  deps = [],
20408
20410
  {
20409
20411
  backgroundElementSelector,
20412
+ colorProperty = "backgroundColor",
20410
20413
  attributeName = "data-dark-background",
20414
+ luminanceThreshold,
20411
20415
  hardcoded = {},
20412
20416
  } = {},
20413
20417
  ) => {
20414
20418
  const innerDeps = [
20415
20419
  ...deps,
20416
- // ref can change is the component pass a different ref on different render based on some logic
20417
- // (can be used to control which element backgroundColor is being checked by switching the ref to another element)
20420
+ // ref can change if the component passes a different ref on different renders
20421
+ // (e.g. to control which element's color is being checked by switching the ref)
20418
20422
  ref,
20419
- // backgroundElementSelector can change if the component pass a different selector on different render based on some logic
20420
- // (can be used to control which element backgroundColor is being checked by switching the selector to point to another element)
20423
+ // backgroundElementSelector can change if the component passes a different selector on different renders
20424
+ // (e.g. to control which child element's color is being checked by switching the selector)
20421
20425
  backgroundElementSelector,
20426
+ colorProperty,
20422
20427
  ];
20423
20428
 
20424
20429
  const hardcodedMap = new Map();
@@ -20443,16 +20448,23 @@ const useDarkBackgroundAttribute = (
20443
20448
  }
20444
20449
  const updateAttribute = () => {
20445
20450
  const computedStyle = getComputedStyle(elementToCheck);
20446
- const backgroundColor = computedStyle.backgroundColor;
20447
- if (!backgroundColor) {
20451
+ const color = computedStyle[colorProperty];
20452
+ if (!color) {
20448
20453
  el.removeAttribute(attributeName);
20449
20454
  return;
20450
20455
  }
20451
- const backgroundColorString = normalizeColorString(backgroundColor, el);
20452
- const hardcodedContrast = hardcodedMap.get(backgroundColorString);
20453
- const contrastingColor =
20454
- hardcodedContrast || contrastColor(backgroundColor, el);
20455
- if (contrastingColor === "white") {
20456
+ const colorString = normalizeColorString(color, el);
20457
+ const hardcodedContrast = hardcodedMap.get(colorString);
20458
+ let isDark;
20459
+ if (hardcodedContrast) {
20460
+ isDark = hardcodedContrast === "white";
20461
+ } else if (luminanceThreshold !== undefined) {
20462
+ const luminance = resolveColorLuminance(color, el);
20463
+ isDark = luminance !== undefined && luminance <= luminanceThreshold;
20464
+ } else {
20465
+ isDark = contrastColor(color, el) === "white";
20466
+ }
20467
+ if (isDark) {
20456
20468
  el.setAttribute(attributeName, "");
20457
20469
  } else {
20458
20470
  el.removeAttribute(attributeName);
@@ -24384,13 +24396,15 @@ installImportMetaCssBuild(import.meta);const css$p = /* css */`
24384
24396
  --outline-color: var(--navi-focus-outline-color);
24385
24397
  --loader-color: var(--navi-loader-color);
24386
24398
  --border-color: light-dark(#767676, #8e8e93);
24387
- --background-color: white;
24399
+ --background-color: rgba(0, 0, 0, 0.15);
24388
24400
  --accent-color: light-dark(#4476ff, #3b82f6);
24389
24401
  --background-color-checked: var(--accent-color);
24390
24402
  --border-color-checked: var(--accent-color);
24391
24403
  --checkmark-color: rgb(55, 55, 55);
24392
24404
  --cursor: pointer;
24393
- --color-mix: white;
24405
+ --color-mix-light: black;
24406
+ --color-mix-dark: white;
24407
+ --color-mix: var(--color-mix-light);
24394
24408
 
24395
24409
  /* Hover */
24396
24410
  --border-color-hover: color-mix(in srgb, var(--border-color) 60%, black);
@@ -24485,7 +24499,7 @@ installImportMetaCssBuild(import.meta);const css$p = /* css */`
24485
24499
  );
24486
24500
 
24487
24501
  &[data-dark-background] {
24488
- --color-mix: black;
24502
+ --color-mix: var(--color-mix-dark);
24489
24503
  --checkmark-color: white;
24490
24504
  }
24491
24505
  }
@@ -24502,6 +24516,15 @@ installImportMetaCssBuild(import.meta);const css$p = /* css */`
24502
24516
  box-sizing: content-box;
24503
24517
  margin: var(--margin);
24504
24518
 
24519
+ .navi_checkbox_accent_probe {
24520
+ position: absolute;
24521
+ width: 0;
24522
+ height: 0;
24523
+ background-color: var(--accent-color);
24524
+ visibility: hidden;
24525
+ pointer-events: none;
24526
+ }
24527
+
24505
24528
  .navi_native_field {
24506
24529
  position: absolute;
24507
24530
  inset: 0;
@@ -24579,6 +24602,14 @@ installImportMetaCssBuild(import.meta);const css$p = /* css */`
24579
24602
  }
24580
24603
  }
24581
24604
 
24605
+ &[data-dark-background]:not([data-appearance="toggle"]) {
24606
+ --x-background-color: white;
24607
+ --x-checkmark-color: var(--checkmark-color);
24608
+ &[data-checked] {
24609
+ --x-background-color: var(--background-color-checked);
24610
+ }
24611
+ }
24612
+
24582
24613
  /* Checkbox appearance */
24583
24614
  &[data-appearance="checkbox"] {
24584
24615
  .navi_checkbox_marker {
@@ -24697,7 +24728,8 @@ installImportMetaCssBuild(import.meta);const css$p = /* css */`
24697
24728
  }
24698
24729
  `;
24699
24730
  const InputCheckbox = props => {
24700
- import.meta.css = [css$p, "@jsenv/navi/src/field/input_checkbox.jsx"];
24731
+ const defaultRef = useRef();
24732
+ const ref = props.ref || defaultRef;
24701
24733
  const {
24702
24734
  value = "on"
24703
24735
  } = props;
@@ -24709,71 +24741,31 @@ const InputCheckbox = props => {
24709
24741
  getPropFromState: Boolean
24710
24742
  });
24711
24743
  const uiState = useUIState(uiStateController);
24712
- const checkbox = renderActionableComponent(props, {
24713
- Basic: InputCheckboxBasic,
24714
- WithAction: InputCheckboxWithAction
24715
- });
24716
24744
  return jsx(UIStateControllerContext.Provider, {
24717
24745
  value: uiStateController,
24718
24746
  children: jsx(UIStateContext.Provider, {
24719
24747
  value: uiState,
24720
- children: checkbox
24748
+ children: jsx(InputCheckboxDispatcher, {
24749
+ ...props,
24750
+ ref: ref
24751
+ })
24721
24752
  })
24722
24753
  });
24723
24754
  };
24724
- const CheckboxStyleCSSVars = {
24725
- "width": "--width",
24726
- "height": "--height",
24727
- "outlineWidth": "--outline-width",
24728
- "borderWidth": "--border-width",
24729
- "backgroundColor": "--background-color",
24730
- "borderColor": "--border-color",
24731
- "accentColor": "--accent-color",
24732
- ":hover": {
24733
- backgroundColor: "--background-color-hover",
24734
- borderColor: "--border-color-hover"
24735
- },
24736
- ":active": {
24737
- borderColor: "--border-color-active"
24738
- },
24739
- ":read-only": {
24740
- backgroundColor: "--background-color-readonly",
24741
- borderColor: "--border-color-readonly"
24742
- },
24743
- ":disabled": {
24744
- backgroundColor: "--background-color-disabled",
24745
- borderColor: "--border-color-disabled"
24755
+ const InputCheckboxDispatcher = props => {
24756
+ if (props.action) {
24757
+ return jsx(InputCheckboxWithAction, {
24758
+ ...props
24759
+ });
24746
24760
  }
24761
+ return jsx(InputCheckboxUI, {
24762
+ ...props
24763
+ });
24747
24764
  };
24748
- const CheckboxToggleStyleCSSVars = {
24749
- ...CheckboxStyleCSSVars,
24750
- width: "--toggle-width",
24751
- height: "--toggle-height",
24752
- borderRadius: "--border-radius"
24753
- };
24754
- const CheckboxButtonStyleCSSVars = {
24755
- ...CheckboxStyleCSSVars,
24756
- paddingTop: "--padding-top",
24757
- paddingRight: "--padding-right",
24758
- paddingBottom: "--padding-bottom",
24759
- paddingLeft: "--padding-left",
24760
- paddingX: "--padding-x",
24761
- paddingY: "--padding-y",
24762
- padding: "--padding"
24763
- };
24764
- const CheckboxPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":checked", ":-navi-loading"];
24765
- const CheckboxPseudoElements = ["::-navi-loader", "::-navi-checkmark"];
24766
- const CheckboxChildPropSet = new Set([...fieldPropSet]);
24767
- const InputCheckboxBasic = props => {
24768
- const contextFieldName = useContext(FieldNameContext);
24769
- const contextReadOnly = useContext(ReadOnlyContext);
24770
- const contextDisabled = useContext(DisabledContext);
24771
- const contextRequired = useContext(RequiredContext);
24772
- const contextLoading = useContext(LoadingContext);
24773
- const loadingElement = useContext(LoadingElementContext);
24774
- const uiStateController = useContext(UIStateControllerContext);
24775
- const uiState = useContext(UIStateContext);
24765
+ const InputCheckboxUI = props => {
24766
+ import.meta.css = [css$p, "@jsenv/navi/src/field/input_checkbox.jsx"];
24776
24767
  const {
24768
+ ref,
24777
24769
  /* eslint-disable no-unused-vars */
24778
24770
  type,
24779
24771
  defaultChecked,
@@ -24794,8 +24786,14 @@ const InputCheckboxBasic = props => {
24794
24786
  // "checkbox", "toggle", "icon", "button"
24795
24787
  ...rest
24796
24788
  } = props;
24797
- const defaultRef = useRef();
24798
- const ref = rest.ref || defaultRef;
24789
+ const contextFieldName = useContext(FieldNameContext);
24790
+ const contextReadOnly = useContext(ReadOnlyContext);
24791
+ const contextDisabled = useContext(DisabledContext);
24792
+ const contextRequired = useContext(RequiredContext);
24793
+ const contextLoading = useContext(LoadingContext);
24794
+ const loadingElement = useContext(LoadingElementContext);
24795
+ const uiStateController = useContext(UIStateControllerContext);
24796
+ const uiState = useContext(UIStateContext);
24799
24797
  const innerName = name || contextFieldName;
24800
24798
  const innerDisabled = disabled || contextDisabled;
24801
24799
  const innerRequired = required || contextRequired;
@@ -24841,13 +24839,9 @@ const InputCheckboxBasic = props => {
24841
24839
  });
24842
24840
  const renderCheckboxMemoized = useCallback(renderCheckbox, [id, innerName, checked, innerRequired]);
24843
24841
  const boxRef = useRef();
24844
- useDarkBackgroundAttribute(boxRef, [accentColor, checked], {
24845
- backgroundElementSelector: ".navi_checkbox_field",
24846
- // the browser (chrome at least) prefer white in this scenario even if
24847
- // the contrast is better with black, so we force it to white to match chrome behavior on this specific color
24848
- hardcoded: {
24849
- "#4476ff": "white"
24850
- }
24842
+ useDarkBackgroundAttribute(boxRef, [accentColor], {
24843
+ backgroundElementSelector: ".navi_checkbox_accent_probe",
24844
+ luminanceThreshold: 0.82
24851
24845
  });
24852
24846
  return jsxs(Box, {
24853
24847
  as: "span",
@@ -24871,7 +24865,10 @@ const InputCheckboxBasic = props => {
24871
24865
  hasChildFunction: true,
24872
24866
  baseChildPropSet: CheckboxChildPropSet,
24873
24867
  preventInitialTransition: true,
24874
- children: [jsx(LoaderBackground, {
24868
+ children: [jsx("span", {
24869
+ className: "navi_checkbox_accent_probe",
24870
+ "aria-hidden": "true"
24871
+ }), jsx(LoaderBackground, {
24875
24872
  loading: innerLoading,
24876
24873
  inset: -1,
24877
24874
  color: "var(--loader-color)",
@@ -24908,10 +24905,54 @@ const InputCheckboxBasic = props => {
24908
24905
  })]
24909
24906
  });
24910
24907
  };
24908
+ const CheckboxStyleCSSVars = {
24909
+ "width": "--width",
24910
+ "height": "--height",
24911
+ "outlineWidth": "--outline-width",
24912
+ "borderWidth": "--border-width",
24913
+ "backgroundColor": "--background-color",
24914
+ "borderColor": "--border-color",
24915
+ "accentColor": "--accent-color",
24916
+ ":hover": {
24917
+ backgroundColor: "--background-color-hover",
24918
+ borderColor: "--border-color-hover"
24919
+ },
24920
+ ":active": {
24921
+ borderColor: "--border-color-active"
24922
+ },
24923
+ ":read-only": {
24924
+ backgroundColor: "--background-color-readonly",
24925
+ borderColor: "--border-color-readonly"
24926
+ },
24927
+ ":disabled": {
24928
+ backgroundColor: "--background-color-disabled",
24929
+ borderColor: "--border-color-disabled"
24930
+ }
24931
+ };
24932
+ const CheckboxToggleStyleCSSVars = {
24933
+ ...CheckboxStyleCSSVars,
24934
+ width: "--toggle-width",
24935
+ height: "--toggle-height",
24936
+ borderRadius: "--border-radius"
24937
+ };
24938
+ const CheckboxButtonStyleCSSVars = {
24939
+ ...CheckboxStyleCSSVars,
24940
+ paddingTop: "--padding-top",
24941
+ paddingRight: "--padding-right",
24942
+ paddingBottom: "--padding-bottom",
24943
+ paddingLeft: "--padding-left",
24944
+ paddingX: "--padding-x",
24945
+ paddingY: "--padding-y",
24946
+ padding: "--padding"
24947
+ };
24948
+ const CheckboxPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":checked", ":-navi-loading"];
24949
+ const CheckboxPseudoElements = ["::-navi-loader", "::-navi-checkmark"];
24950
+ const CheckboxChildPropSet = new Set([...fieldPropSet]);
24911
24951
  const InputCheckboxWithAction = props => {
24912
24952
  const uiStateController = useContext(UIStateControllerContext);
24913
24953
  const uiState = useContext(UIStateContext);
24914
24954
  const {
24955
+ ref,
24915
24956
  action,
24916
24957
  onCancel,
24917
24958
  actionErrorEffect,
@@ -24923,8 +24964,6 @@ const InputCheckboxWithAction = props => {
24923
24964
  loading,
24924
24965
  ...rest
24925
24966
  } = props;
24926
- const defaultRef = useRef();
24927
- const ref = props.ref || defaultRef;
24928
24967
  const [actionBoundToUIState] = useActionBoundToOneParam(action, uiState);
24929
24968
  const actionStatus = useActionStatus(actionBoundToUIState);
24930
24969
  const {
@@ -24961,7 +25000,7 @@ const InputCheckboxWithAction = props => {
24961
25000
  onActionEnd?.(e);
24962
25001
  }
24963
25002
  });
24964
- return jsx(InputCheckboxBasic, {
25003
+ return jsx(InputCheckboxDispatcher, {
24965
25004
  "data-action": actionBoundToUIState.name,
24966
25005
  ...rest,
24967
25006
  ref: ref,
@@ -25123,19 +25162,19 @@ installImportMetaCssBuild(import.meta);const css$o = /* css */`
25123
25162
  --width: 0.815em;
25124
25163
  --height: 0.815em;
25125
25164
 
25165
+ --color-mix-light: black;
25166
+ --color-mix-dark: white;
25167
+ --color-mix: var(--color-mix-light);
25168
+
25126
25169
  --outline-color: var(--navi-focus-outline-color);
25127
25170
  --loader-color: var(--navi-loader-color);
25128
25171
  --border-color: light-dark(#767676, #8e8e93);
25129
- --background-color: white;
25172
+ --x-background-color: rgba(0, 0, 0, 0.15);
25130
25173
  --accent-color: light-dark(#4476ff, #3b82f6);
25131
25174
  --radiomark-color: var(--accent-color);
25132
25175
  --border-color-checked: var(--accent-color);
25133
25176
  --cursor: pointer;
25134
25177
 
25135
- --color-mix-light: black;
25136
- --color-mix-dark: white;
25137
- --color-mix: var(--color-mix-light);
25138
-
25139
25178
  /* Hover */
25140
25179
  --border-color-hover: color-mix(in srgb, var(--border-color) 60%, black);
25141
25180
  --border-color-hover-checked: color-mix(
@@ -25194,10 +25233,6 @@ installImportMetaCssBuild(import.meta);const css$o = /* css */`
25194
25233
  --button-border-color-disabled: var(--border-color-readonly);
25195
25234
  --button-background-color-disabled: var(--background-color-readonly);
25196
25235
  }
25197
-
25198
- &[data-dark] {
25199
- --color-mix: var(--color-mix-dark);
25200
- }
25201
25236
  }
25202
25237
 
25203
25238
  .navi_radio {
@@ -25217,6 +25252,15 @@ installImportMetaCssBuild(import.meta);const css$o = /* css */`
25217
25252
  box-sizing: content-box;
25218
25253
  margin: var(--margin);
25219
25254
 
25255
+ .navi_radio_accent_probe {
25256
+ position: absolute;
25257
+ width: 0;
25258
+ height: 0;
25259
+ background-color: var(--accent-color);
25260
+ visibility: hidden;
25261
+ pointer-events: none;
25262
+ }
25263
+
25220
25264
  .navi_native_field {
25221
25265
  position: absolute;
25222
25266
  inset: 0;
@@ -25243,6 +25287,7 @@ installImportMetaCssBuild(import.meta);const css$o = /* css */`
25243
25287
  }
25244
25288
  /* Checked */
25245
25289
  &[data-checked] {
25290
+ --x-background-color: transparent;
25246
25291
  --x-border-color: var(--border-color-checked);
25247
25292
 
25248
25293
  &[data-hover] {
@@ -25279,6 +25324,14 @@ installImportMetaCssBuild(import.meta);const css$o = /* css */`
25279
25324
  }
25280
25325
  }
25281
25326
 
25327
+ &[data-dark-background] {
25328
+ --x-background-color: white;
25329
+ --color-mix: var(--color-mix-dark);
25330
+ &[data-checked] {
25331
+ --x-background-color: white;
25332
+ }
25333
+ }
25334
+
25282
25335
  .navi_radio_field {
25283
25336
  box-sizing: border-box;
25284
25337
  width: var(--x-width);
@@ -25407,7 +25460,8 @@ installImportMetaCssBuild(import.meta);const css$o = /* css */`
25407
25460
  }
25408
25461
  `;
25409
25462
  const InputRadio = props => {
25410
- import.meta.css = [css$o, "@jsenv/navi/src/field/input_radio.jsx"];
25463
+ const defaultRef = useRef();
25464
+ const ref = props.ref || defaultRef;
25411
25465
  const {
25412
25466
  value = "on"
25413
25467
  } = props;
@@ -25424,76 +25478,29 @@ const InputRadio = props => {
25424
25478
  }
25425
25479
  });
25426
25480
  const uiState = useUIState(uiStateController);
25427
- const radio = renderActionableComponent(props, {
25428
- Basic: InputRadioBasic,
25429
- WithAction: InputRadioWithAction
25430
- });
25431
25481
  return jsx(UIStateControllerContext.Provider, {
25432
25482
  value: uiStateController,
25433
25483
  children: jsx(UIStateContext.Provider, {
25434
25484
  value: uiState,
25435
- children: radio
25485
+ children: jsx(InputRadioDispatcher, {
25486
+ ...props,
25487
+ ref: ref
25488
+ })
25436
25489
  })
25437
25490
  });
25438
25491
  };
25439
- const RadioStyleCSSVars = {
25440
- "width": "--width",
25441
- "height": "--height",
25442
- "borderRadius": "--border-radius",
25443
- "outlineWidth": "--outline-width",
25444
- "borderWidth": "--border-width",
25445
- "backgroundColor": "--background-color",
25446
- "borderColor": "--border-color",
25447
- "accentColor": "--accent-color",
25448
- ":hover": {
25449
- backgroundColor: "--background-color-hover",
25450
- borderColor: "--border-color-hover"
25451
- },
25452
- ":active": {
25453
- borderColor: "--border-color-active"
25454
- },
25455
- ":read-only": {
25456
- backgroundColor: "--background-color-readonly",
25457
- borderColor: "--border-color-readonly"
25458
- },
25459
- ":disabled": {
25460
- backgroundColor: "--background-color-disabled",
25461
- borderColor: "--border-color-disabled"
25462
- }
25463
- };
25464
- const RadioButtonStyleCSSVars = {
25465
- ...RadioStyleCSSVars,
25466
- "padding": "--padding",
25467
- "borderRadius": "--button-border-radius",
25468
- "borderWidth": "--button-border-width",
25469
- "borderColor": "--button-border-color",
25470
- "backgroundColor": "--button-background-color",
25471
- ":hover": {
25472
- backgroundColor: "--button-background-color-hover",
25473
- borderColor: "--button-border-color-hover"
25474
- },
25475
- ":read-only": {
25476
- backgroundColor: "--button-background-color-readonly",
25477
- borderColor: "--button-border-color-readonly"
25478
- },
25479
- ":disabled": {
25480
- backgroundColor: "--button-background-color-disabled",
25481
- borderColor: "--button-border-color-disabled"
25492
+ const InputRadioDispatcher = props => {
25493
+ if (props.action) {
25494
+ return jsx(InputRadioWithAction, {});
25482
25495
  }
25496
+ return jsx(InputRadioUI, {
25497
+ ...props
25498
+ });
25483
25499
  };
25484
- const RadioPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":checked", ":-navi-loading"];
25485
- const RadioPseudoElements = ["::-navi-loader", "::-navi-radiomark"];
25486
- const RadioChildPropSet = new Set([...fieldPropSet]);
25487
- const InputRadioBasic = props => {
25488
- const contextName = useContext(FieldNameContext);
25489
- const contextReadOnly = useContext(ReadOnlyContext);
25490
- const contextDisabled = useContext(DisabledContext);
25491
- const contextRequired = useContext(RequiredContext);
25492
- const contextLoading = useContext(LoadingContext);
25493
- const contextLoadingElement = useContext(LoadingElementContext);
25494
- const uiStateController = useContext(UIStateControllerContext);
25495
- const uiState = useContext(UIStateContext);
25500
+ const InputRadioUI = props => {
25501
+ import.meta.css = [css$o, "@jsenv/navi/src/field/input_radio.jsx"];
25496
25502
  const {
25503
+ ref,
25497
25504
  /* eslint-disable no-unused-vars */
25498
25505
  type,
25499
25506
  /* eslint-enable no-unused-vars */
@@ -25511,8 +25518,14 @@ const InputRadioBasic = props => {
25511
25518
  color,
25512
25519
  ...rest
25513
25520
  } = props;
25514
- const defaultRef = useRef();
25515
- const ref = rest.ref || defaultRef;
25521
+ const contextName = useContext(FieldNameContext);
25522
+ const contextReadOnly = useContext(ReadOnlyContext);
25523
+ const contextDisabled = useContext(DisabledContext);
25524
+ const contextRequired = useContext(RequiredContext);
25525
+ const contextLoading = useContext(LoadingContext);
25526
+ const contextLoadingElement = useContext(LoadingElementContext);
25527
+ const uiStateController = useContext(UIStateControllerContext);
25528
+ const uiState = useContext(UIStateContext);
25516
25529
  const innerName = name || contextName;
25517
25530
  const innerDisabled = disabled || contextDisabled;
25518
25531
  const innerRequired = required || contextRequired;
@@ -25586,15 +25599,10 @@ const InputRadioBasic = props => {
25586
25599
  });
25587
25600
  const renderRadioMemoized = useCallback(renderRadio, [innerName, checked, innerRequired]);
25588
25601
  const boxRef = useRef();
25589
- useLayoutEffect(() => {
25590
- const naviRadio = boxRef.current;
25591
- const luminance = resolveColorLuminance("var(--accent-color)", naviRadio);
25592
- if (luminance < 0.3) {
25593
- naviRadio.setAttribute("data-dark", "");
25594
- } else {
25595
- naviRadio.removeAttribute("data-dark");
25596
- }
25597
- }, [color]);
25602
+ useDarkBackgroundAttribute(boxRef, [remainingProps.accentColor], {
25603
+ backgroundElementSelector: ".navi_radio_accent_probe",
25604
+ luminanceThreshold: 0.82
25605
+ });
25598
25606
  return jsxs(Box, {
25599
25607
  as: "span",
25600
25608
  ...remainingProps,
@@ -25616,7 +25624,10 @@ const InputRadioBasic = props => {
25616
25624
  color: color,
25617
25625
  hasChildFunction: true,
25618
25626
  baseChildPropSet: RadioChildPropSet,
25619
- children: [jsx(LoaderBackground, {
25627
+ children: [jsx("span", {
25628
+ className: "navi_radio_accent_probe",
25629
+ "aria-hidden": "true"
25630
+ }), jsx(LoaderBackground, {
25620
25631
  loading: innerLoading,
25621
25632
  inset: -1,
25622
25633
  targetSelector: ".navi_radio_field",
@@ -25652,6 +25663,54 @@ const InputRadioBasic = props => {
25652
25663
  })]
25653
25664
  });
25654
25665
  };
25666
+ const RadioStyleCSSVars = {
25667
+ "width": "--width",
25668
+ "height": "--height",
25669
+ "borderRadius": "--border-radius",
25670
+ "outlineWidth": "--outline-width",
25671
+ "borderWidth": "--border-width",
25672
+ "backgroundColor": "--background-color",
25673
+ "borderColor": "--border-color",
25674
+ "accentColor": "--accent-color",
25675
+ ":hover": {
25676
+ backgroundColor: "--background-color-hover",
25677
+ borderColor: "--border-color-hover"
25678
+ },
25679
+ ":active": {
25680
+ borderColor: "--border-color-active"
25681
+ },
25682
+ ":read-only": {
25683
+ backgroundColor: "--background-color-readonly",
25684
+ borderColor: "--border-color-readonly"
25685
+ },
25686
+ ":disabled": {
25687
+ backgroundColor: "--background-color-disabled",
25688
+ borderColor: "--border-color-disabled"
25689
+ }
25690
+ };
25691
+ const RadioButtonStyleCSSVars = {
25692
+ ...RadioStyleCSSVars,
25693
+ "padding": "--padding",
25694
+ "borderRadius": "--button-border-radius",
25695
+ "borderWidth": "--button-border-width",
25696
+ "borderColor": "--button-border-color",
25697
+ "backgroundColor": "--button-background-color",
25698
+ ":hover": {
25699
+ backgroundColor: "--button-background-color-hover",
25700
+ borderColor: "--button-border-color-hover"
25701
+ },
25702
+ ":read-only": {
25703
+ backgroundColor: "--button-background-color-readonly",
25704
+ borderColor: "--button-border-color-readonly"
25705
+ },
25706
+ ":disabled": {
25707
+ backgroundColor: "--button-background-color-disabled",
25708
+ borderColor: "--button-border-color-disabled"
25709
+ }
25710
+ };
25711
+ const RadioPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":checked", ":-navi-loading"];
25712
+ const RadioPseudoElements = ["::-navi-loader", "::-navi-radiomark"];
25713
+ const RadioChildPropSet = new Set([...fieldPropSet]);
25655
25714
  const InputRadioWithAction = () => {
25656
25715
  throw new Error(`<Input type="radio" /> with an action make no sense. Use <RadioList action={something} /> instead`);
25657
25716
  };
@@ -26637,10 +26696,13 @@ const css$m = /* css */`
26637
26696
  --list-item-color-selected: light-dark(#1a73e8, #7baaf7);
26638
26697
  --list-item-background-color-selected: light-dark(#e8f0fe, #1c3a6e);
26639
26698
  --list-item-font-weight-selected: 500;
26699
+
26700
+ /* Pointed+selected: darken the selected background slightly */
26640
26701
  --list-item-color-pointed-selected: var(--list-item-color-selected);
26641
- --list-item-background-color-pointed-selected: light-dark(
26642
- #d2e3fc,
26643
- #174ea6
26702
+ --list-item-background-color-pointed-selected: color-mix(
26703
+ in srgb,
26704
+ var(--list-item-background-color-selected) 80%,
26705
+ black
26644
26706
  );
26645
26707
 
26646
26708
  /* Disabled */
@@ -26981,8 +27043,8 @@ const ListUI = props => {
26981
27043
  renderBudget = RENDER_BUDGET_DEFAULT,
26982
27044
  listId,
26983
27045
  listRole,
26984
- fallback = "Aucun élément dans cette liste",
26985
- noMatchFallback = "Aucun élément ne correspond à cette recherche",
27046
+ fallback,
27047
+ noMatchFallback,
26986
27048
  separator,
26987
27049
  children,
26988
27050
  popover,
@@ -27516,11 +27578,11 @@ const UnorderedList = ({
27516
27578
  children: [jsx(TopFiller, {
27517
27579
  virtualItemHeightSignal: virtualItemHeightSignal,
27518
27580
  renderWindowStart: renderWindow.start
27519
- }), noMatchFallback && jsx(NoMatchFallback, {
27581
+ }), jsx(NoMatchFallback, {
27520
27582
  noMatchFallback: noMatchFallback,
27521
27583
  tracker: tracker,
27522
27584
  searchText: searchText
27523
- }), fallback && jsx(Fallback, {
27585
+ }), jsx(Fallback, {
27524
27586
  fallback: fallback,
27525
27587
  tracker: tracker
27526
27588
  }), jsx(RenderWindowContext.Provider, {
@@ -27552,12 +27614,15 @@ const NoMatchFallback = ({
27552
27614
  const allHidden = itemCount > 0 && visibleItemCount === 0;
27553
27615
  const noneMatch = searchText && visibleItemCount > 0 && matchCount === 0;
27554
27616
  const showMatchFallback = allHidden || noneMatch;
27617
+ if (noMatchFallback === undefined) {
27618
+ noMatchFallback = allHidden ? "Aucun élément ne correspond à cette recherche." : "Aucun élément ne correspond à cette recherche. Le reste est affiché ci-dessous";
27619
+ }
27555
27620
  return jsx(ListItem, {
27556
27621
  role: "presentation",
27557
27622
  className: "navi_list_item navi_list_no_match_fallback",
27558
27623
  hidden: !showMatchFallback,
27559
27624
  "navi-default": typeof noMatchFallback === "string" ? "" : undefined,
27560
- children: allHidden ? "Aucun élément ne correspond à cette recherche" : "Aucun élément ne correspond à cette recherche. Le reste est affiché ci-dessous"
27625
+ children: noMatchFallback
27561
27626
  });
27562
27627
  };
27563
27628
  const Fallback = ({
@@ -27566,6 +27631,9 @@ const Fallback = ({
27566
27631
  }) => {
27567
27632
  const itemCount = tracker.countSignal.value;
27568
27633
  const showFallback = itemCount === 0;
27634
+ if (fallback === undefined) {
27635
+ fallback = "Aucun élément dans cette liste.";
27636
+ }
27569
27637
  return jsx(ListItem, {
27570
27638
  role: "presentation",
27571
27639
  className: "navi_list_item navi_list_fallback",
@@ -28226,13 +28294,13 @@ const ListItemReal = ({
28226
28294
  ...rest,
28227
28295
  ref: ref,
28228
28296
  basePseudoState: {
28297
+ ...rest.basePseudoState,
28298
+ ":disabled": Boolean(disabled),
28229
28299
  ":-navi-pointed": isPointed,
28230
28300
  ":-navi-pointed-by-mouse": isPointedByMouse,
28231
28301
  ":-navi-pointed-by-keyboard": isPointedByKeyboard,
28232
28302
  ":-navi-pointed-by-proxy": isPointedByProxy,
28233
- ":-navi-selected": selected,
28234
- ":disabled": Boolean(disabled),
28235
- ...rest.basePseudoState
28303
+ ":-navi-selected": selected
28236
28304
  },
28237
28305
  children: children
28238
28306
  });