@jsenv/navi 0.1.1 → 0.2.0

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.
@@ -8,9 +8,16 @@ import {
8
8
 
9
9
  import { useConstraints } from "../../validation/hooks/use_constraints.js";
10
10
  import { renderActionableComponent } from "../action_execution/render_actionable_component.jsx";
11
- import { LoadableInlineElement } from "../loader/loader_background.jsx";
11
+ import {
12
+ LoadableInlineElement,
13
+ LoaderBackground,
14
+ } from "../loader/loader_background.jsx";
12
15
  import { useAutoFocus } from "../use_auto_focus.js";
13
- import { ReportReadOnlyOnLabelContext } from "./label.jsx";
16
+ import { initCustomField } from "./custom_field.js";
17
+ import {
18
+ ReportDisabledOnLabelContext,
19
+ ReportReadOnlyOnLabelContext,
20
+ } from "./label.jsx";
14
21
  import {
15
22
  DisabledContext,
16
23
  FieldNameContext,
@@ -25,169 +32,152 @@ import {
25
32
  } from "./use_ui_state_controller.js";
26
33
 
27
34
  import.meta.css = /* css */ `
28
- .custom_radio_wrapper {
35
+ :root {
36
+ --navi-radiomark-color: light-dark(#4476ff, #3b82f6);
37
+ }
38
+
39
+ .navi_radio {
29
40
  position: relative;
30
41
  display: inline-flex;
31
42
  box-sizing: content-box;
32
43
 
33
- --checked-color: #3b82f6;
34
- --checked-disabled-color: var(--field-disabled-border-color);
44
+ --outline-offset: 1px;
45
+ --outline-width: 2px;
46
+ --width: 13px;
47
+ --height: 13px;
35
48
 
36
- --checkmark-color: var(--checked-color);
37
- --checkmark-disabled-color: var(--field-disabled-text-color);
38
- }
49
+ --outline-color: light-dark(#4476ff, #3b82f6);
50
+ --border-color: light-dark(#767676, #8e8e93);
51
+ --background-color: white;
52
+ --accent-color: var(--navi-radiomark-color);
53
+ --mark-color: var(--accent-color);
54
+
55
+ /* light-dark(rgba(239, 239, 239, 0.3), rgba(59, 59, 59, 0.3)); */
56
+ --accent-color-checked: color-mix(in srgb, var(--accent-color) 70%, black);
39
57
 
40
- .custom_radio_wrapper input {
58
+ --border-color-readonly: color-mix(in srgb, var(--border-color) 30%, white);
59
+ --border-color-disabled: var(--border-color-readonly);
60
+ --border-color-hover: color-mix(in srgb, var(--border-color) 70%, black);
61
+ --border-color-checked: var(--accent-color);
62
+ --border-color-checked-hover: var(--accent-color-checked);
63
+ --border-color-checked-readonly: #d3d3d3;
64
+ --border-color-checked-disabled: #d3d3d3;
65
+ --background-color-readonly: var(--background-color);
66
+ --background-color-disabled: var(--background-color);
67
+ --background-color-checked-readonly: #d3d3d3;
68
+ --background-color-checked-disabled: var(--background-color);
69
+ --mark-color-hover: var(--accent-color-checked);
70
+ --mark-color-readonly: grey;
71
+ --mark-color-disabled: #eeeeee;
72
+ }
73
+ .navi_radio input {
41
74
  position: absolute;
42
- opacity: 0;
43
75
  inset: 0;
44
76
  margin: 0;
45
77
  padding: 0;
46
- border: none;
78
+ opacity: 0;
79
+ cursor: inherit;
47
80
  }
48
-
49
- .custom_radio {
50
- width: 13px;
51
- height: 13px;
52
- background: transparent;
53
- border-radius: 50%;
81
+ .navi_radio_field {
54
82
  display: inline-flex;
55
- align-items: center;
56
- justify-content: center;
57
- margin-left: 5px;
83
+ width: var(--width);
84
+ height: var(--height);
58
85
  margin-top: 3px;
59
86
  margin-right: 3px;
60
- }
87
+ margin-left: 5px;
88
+ align-items: center;
89
+ justify-content: center;
90
+ border-radius: 50%;
91
+ outline-width: var(--outline-width);
92
+
93
+ outline-style: none;
61
94
 
62
- .custom_radio svg {
95
+ outline-color: var(--outline-color);
96
+
97
+ outline-offset: var(--outline-offset);
98
+ }
99
+ .navi_radio_field svg {
100
+ overflow: visible;
101
+ }
102
+ .navi_radio_border {
103
+ fill: var(--background-color);
104
+ stroke: var(--border-color);
105
+ }
106
+ .navi_radio_marker {
63
107
  width: 100%;
64
108
  height: 100%;
109
+ opacity: 0;
110
+ fill: var(--mark-color);
111
+ transform: scale(0.3);
112
+ transform-origin: center;
65
113
  pointer-events: none;
66
114
  }
67
-
68
- .custom_radio svg .custom_radio_dashed_border {
115
+ .navi_radio_dashed_border {
69
116
  display: none;
70
117
  }
71
-
72
- .custom_radio svg .custom_radio_marker {
73
- fill: var(--checkmark-color);
74
- opacity: 0;
75
- transform-origin: center;
76
- transform: scale(0.3);
77
- }
78
-
79
- .custom_radio[data-transition] svg {
118
+ .navi_radio[data-transition] .navi_radio_marker {
80
119
  transition: all 0.15s ease;
81
120
  }
82
- .custom_radio[data-transition] svg .custom_radio_dashed_border {
121
+ .navi_radio[data-transition] .navi_radio_dashed_border {
83
122
  transition: all 0.15s ease;
84
123
  }
85
- .custom_radio[data-transition] svg .custom_radio_border {
124
+ .navi_radio[data-transition] .navi_radio_border {
86
125
  transition: all 0.15s ease;
87
126
  }
88
127
 
89
- /* États hover */
90
- .custom_radio_wrapper:hover .custom_radio svg .custom_radio_border {
91
- stroke: var(--field-hover-border-color);
128
+ /* Focus */
129
+ .navi_radio[data-focus-visible] .navi_radio_field {
130
+ outline-style: solid;
92
131
  }
93
- .custom_radio_wrapper:hover .custom_radio svg .custom_radio_marker {
94
- fill: var(--field-strong-color);
132
+ /* Hover */
133
+ .navi_radio[data-hover] .navi_radio_border {
134
+ stroke: var(--border-color-hover);
95
135
  }
96
-
97
- .custom_radio_wrapper:hover
98
- input:checked
99
- + .custom_radio
100
- svg
101
- .custom_radio_border {
102
- stroke: var(--field-strong-color);
136
+ .navi_radio[data-hover] .navi_radio_marker {
137
+ fill: var(--mark-color-hover);
103
138
  }
104
-
105
- /* État checked */
106
- .custom_radio_wrapper input:checked + .custom_radio svg .custom_radio_border {
107
- stroke: var(--field-strong-color);
139
+ /* Checked */
140
+ .navi_radio[data-checked] .navi_radio_border {
141
+ stroke: var(--border-color-checked);
108
142
  }
109
-
110
- .custom_radio_wrapper input:checked + .custom_radio svg .custom_radio_marker {
143
+ .navi_radio[data-checked] .navi_radio_marker {
111
144
  opacity: 1;
112
145
  transform: scale(1);
113
146
  }
114
-
115
- /* États disabled */
116
- .custom_radio_wrapper
117
- input[disabled]
118
- + .custom_radio
119
- svg
120
- .custom_radio_border {
121
- fill: light-dark(rgba(239, 239, 239, 0.3), rgba(59, 59, 59, 0.3));
122
- stroke: var(--field-disabled-border-color);
123
- }
124
-
125
- .custom_radio_wrapper
126
- input[disabled]:checked
127
- + .custom_radio
128
- svg
129
- .custom_radio_border {
130
- stroke: var(--checked-disabled-color);
147
+ .navi_radio[data-hover][data-checked] .navi_radio_border {
148
+ stroke: var(--border-color-checked-hover);
131
149
  }
132
-
133
- .custom_radio_wrapper
134
- input[disabled]:checked
135
- + .custom_radio
136
- svg
137
- .custom_radio_marker {
138
- fill: var(--checkmark-disabled-color);
150
+ /* Readonly */
151
+ .navi_radio[data-readonly] .navi_radio_border {
152
+ fill: var(--background-color-readonly);
153
+ stroke: var(--border-color-readonly);
139
154
  }
140
-
141
- .custom_radio_wrapper
142
- input[data-readonly]
143
- + .custom_radio
144
- svg
145
- .custom_radio_border {
146
- fill: light-dark(rgba(239, 239, 239, 0.3), rgba(59, 59, 59, 0.3));
147
- stroke: var(--field-disabled-border-color);
155
+ .navi_radio[data-readonly] .navi_radio_marker {
156
+ fill: var(--mark-color-readonly);
148
157
  }
149
- .custom_radio_wrapper
150
- input[data-readonly]
151
- + .custom_radio
152
- svg
153
- .custom_radio_dashed_border {
158
+ .navi_radio[data-readonly] .navi_radio_dashed_border {
154
159
  display: none;
155
160
  }
156
- .custom_radio_wrapper
157
- input[data-readonly]:checked
158
- + .custom_radio
159
- svg
160
- .custom_radio_border {
161
- stroke: var(--checked-disabled-color);
161
+ .navi_radio[data-checked][data-readonly] .navi_radio_border {
162
+ fill: var(--background-color-checked-readonly);
163
+ stroke: var(--border-color-checked-readonly);
162
164
  }
163
- .custom_radio_wrapper
164
- input[data-readonly]:checked
165
- + .custom_radio
166
- svg
167
- .custom_radio_marker {
168
- fill: var(--checkmark-disabled-color);
165
+ .navi_radio[data-checked][data-readonly] .navi_radio_marker {
166
+ fill: var(--mark-color-readonly);
169
167
  }
170
- .custom_radio_wrapper:hover
171
- input[data-readonly]
172
- + .custom_radio
173
- svg
174
- .custom_radio_border {
175
- fill: light-dark(rgba(239, 239, 239, 0.3), rgba(59, 59, 59, 0.3));
176
- stroke: var(--field-disabled-border-color);
168
+ /* Disabled */
169
+ .navi_radio[data-disabled] .navi_radio_border {
170
+ fill: var(--background-color-disabled);
171
+ stroke: var(--border-color-disabled);
177
172
  }
178
- .custom_radio_wrapper:hover
179
- input[data-readonly]:checked
180
- + .custom_radio
181
- svg
182
- .custom_radio_border {
183
- stroke: var(--checked-disabled-color);
173
+ .navi_radio[data-disabled] .navi_radio_marker {
174
+ fill: var(--mark-color-disabled);
184
175
  }
185
-
186
- /* Focus state avec outline */
187
- .custom_radio_wrapper input:focus-visible + .custom_radio {
188
- outline: 2px solid var(--field-outline-color);
189
- outline-offset: 1px;
190
- border-radius: 50%;
176
+ .navi_radio[data-hover][data-checked][data-disabled] .navi_radio_border {
177
+ stroke: var(--border-color-disabled);
178
+ }
179
+ .navi_radio[data-checked][data-disabled] .navi_radio_marker {
180
+ fill: var(--mark-color-disabled);
191
181
  }
192
182
  `;
193
183
 
@@ -223,6 +213,7 @@ const InputRadioBasic = forwardRef((props, ref) => {
223
213
  const uiStateController = useContext(UIStateControllerContext);
224
214
  const uiState = useContext(UIStateContext);
225
215
  const reportReadOnlyOnLabel = useContext(ReportReadOnlyOnLabelContext);
216
+ const reportDisabledOnLabel = useContext(ReportDisabledOnLabelContext);
226
217
  const {
227
218
  name,
228
219
  readOnly,
@@ -233,10 +224,11 @@ const InputRadioBasic = forwardRef((props, ref) => {
233
224
  autoFocus,
234
225
  constraints = [],
235
226
 
236
- appeareance = "custom", // "custom" or "default"
227
+ appeareance = "navi", // "navi" or "default"
237
228
  accentColor,
238
229
  onClick,
239
230
  onInput,
231
+ style,
240
232
  ...rest
241
233
  } = props;
242
234
  const innerRef = useRef(null);
@@ -251,14 +243,10 @@ const InputRadioBasic = forwardRef((props, ref) => {
251
243
  readOnly || contextReadOnly || innerLoading || uiStateController.readOnly;
252
244
 
253
245
  reportReadOnlyOnLabel?.(innerReadOnly);
246
+ reportDisabledOnLabel?.(innerDisabled);
254
247
  useAutoFocus(innerRef, autoFocus);
255
248
  useConstraints(innerRef, constraints);
256
249
  const checked = Boolean(uiState);
257
- const actionName = rest["data-action"];
258
- if (actionName) {
259
- delete rest["data-action"];
260
- }
261
-
262
250
  // we must first dispatch an event to inform all other radios they where unchecked
263
251
  // this way each other radio uiStateController knows thery are unchecked
264
252
  // we do this on "input"
@@ -266,6 +254,9 @@ const InputRadioBasic = forwardRef((props, ref) => {
266
254
  const updateOtherRadiosInGroup = () => {
267
255
  const thisRadio = innerRef.current;
268
256
  const radioList = thisRadio.closest("[data-radio-list]");
257
+ if (!radioList) {
258
+ return;
259
+ }
269
260
  const radioInputs = radioList.querySelectorAll(
270
261
  `input[type="radio"][name="${thisRadio.name}"]`,
271
262
  );
@@ -284,14 +275,18 @@ const InputRadioBasic = forwardRef((props, ref) => {
284
275
  }
285
276
  }, [checked]);
286
277
 
278
+ const actionName = rest["data-action"];
279
+ if (actionName) {
280
+ delete rest["data-action"];
281
+ }
287
282
  const inputRadio = (
288
283
  <input
289
284
  {...rest}
290
285
  ref={innerRef}
291
286
  type="radio"
287
+ style={appeareance === "default" ? style : undefined}
292
288
  name={innerName}
293
289
  checked={checked}
294
- data-readonly={innerReadOnly ? "" : undefined}
295
290
  disabled={innerDisabled}
296
291
  required={innerRequired}
297
292
  data-validation-message-arrow-x="center"
@@ -320,30 +315,65 @@ const InputRadioBasic = forwardRef((props, ref) => {
320
315
  }}
321
316
  />
322
317
  );
323
- const inputRadioDisplayed =
324
- appeareance === "custom" ? (
325
- <CustomRadio accentColor={accentColor}>{inputRadio}</CustomRadio>
326
- ) : (
327
- inputRadio
318
+ const loaderProps = {
319
+ loading: innerLoading,
320
+ inset: -1,
321
+ style: {
322
+ "--accent-color": accentColor || "light-dark(#355fcc, #4476ff)",
323
+ },
324
+ color: "var(--accent-color)",
325
+ };
326
+ if (appeareance === "navi") {
327
+ return (
328
+ <NaviRadio
329
+ data-action={actionName}
330
+ inputRef={innerRef}
331
+ accentColor={accentColor}
332
+ readOnly={innerReadOnly}
333
+ disabled={innerDisabled}
334
+ style={style}
335
+ >
336
+ <LoaderBackground {...loaderProps} targetSelector=".navi_radio_field">
337
+ {inputRadio}
338
+ </LoaderBackground>
339
+ </NaviRadio>
328
340
  );
341
+ }
329
342
 
330
343
  return (
331
- <LoadableInlineElement
332
- data-action={actionName}
333
- loading={innerLoading}
334
- targetSelector={appeareance === "custom" ? ".custom_radio" : ""}
335
- inset={-1}
336
- color="light-dark(#355fcc, #3b82f6)"
337
- >
338
- {inputRadioDisplayed}
344
+ <LoadableInlineElement {...loaderProps} data-action={actionName}>
345
+ {inputRadio}
339
346
  </LoadableInlineElement>
340
347
  );
341
348
  });
342
- const CustomRadio = ({ children }) => {
349
+ const NaviRadio = ({
350
+ inputRef,
351
+ accentColor,
352
+ readOnly,
353
+ disabled,
354
+ style,
355
+ children,
356
+ ...rest
357
+ }) => {
358
+ const ref = useRef();
359
+ useLayoutEffect(() => {
360
+ return initCustomField(ref.current, inputRef.current);
361
+ }, []);
362
+
343
363
  return (
344
- <div className="custom_radio_wrapper" data-field-wrapper="">
364
+ <span
365
+ {...rest}
366
+ ref={ref}
367
+ className="navi_radio"
368
+ style={{
369
+ ...(accentColor ? { "--accent-color": accentColor } : {}),
370
+ ...style,
371
+ }}
372
+ data-readonly={readOnly ? "" : undefined}
373
+ data-disabled={disabled ? "" : undefined}
374
+ >
345
375
  {children}
346
- <div className="custom_radio">
376
+ <span className="navi_radio_field">
347
377
  <svg
348
378
  viewBox="0 0 12 12"
349
379
  aria-hidden="true"
@@ -351,31 +381,27 @@ const CustomRadio = ({ children }) => {
351
381
  >
352
382
  {/* Border circle - always visible */}
353
383
  <circle
354
- className="custom_radio_border"
384
+ className="navi_radio_border"
355
385
  cx="6"
356
386
  cy="6"
357
387
  r="5.5"
358
- fill="white"
359
- stroke="var(--field-border-color)"
360
388
  strokeWidth="1"
361
389
  />
362
390
  {/* Dashed border for readonly - calculated for even distribution */}
363
391
  <circle
364
- className="custom_radio_dashed_border"
392
+ className="navi_radio_dashed_border"
365
393
  cx="6"
366
394
  cy="6"
367
395
  r="5.5"
368
- fill="var(--field-readonly-background-color)"
369
- stroke="var(--field-border-color)"
370
396
  strokeWidth="1"
371
397
  strokeDasharray="2.16 2.16"
372
398
  strokeDashoffset="0"
373
399
  />
374
400
  {/* Inner fill circle - only visible when checked */}
375
- <circle className="custom_radio_marker" cx="6" cy="6" r="3.5" />
401
+ <circle className="navi_radio_marker" cx="6" cy="6" r="3.5" />
376
402
  </svg>
377
- </div>
378
- </div>
403
+ </span>
404
+ </span>
379
405
  );
380
406
  };
381
407
 
@@ -33,6 +33,7 @@ import { useActionBoundToOneParam } from "../action_execution/use_action.js";
33
33
  import { useExecuteAction } from "../action_execution/use_execute_action.js";
34
34
  import { LoadableInlineElement } from "../loader/loader_background.jsx";
35
35
  import { useAutoFocus } from "../use_auto_focus.js";
36
+ import { initCustomField } from "./custom_field.js";
36
37
  import "./field_css.js";
37
38
  import { ReportReadOnlyOnLabelContext } from "./label.jsx";
38
39
  import { useActionEvents } from "./use_action_events.js";
@@ -47,6 +48,84 @@ import {
47
48
  useUIStateController,
48
49
  } from "./use_ui_state_controller.js";
49
50
 
51
+ import.meta.css = /* css */ `
52
+ .navi_input {
53
+ --border-width: 1px;
54
+ --outline-width: 1px;
55
+ --outer-width: calc(var(--border-width) + var(--outline-width));
56
+ --padding-x: 6px;
57
+ --padding-y: 1px;
58
+
59
+ --outline-color: light-dark(#4476ff, #3b82f6);
60
+
61
+ --border-radius: 2px;
62
+ --border-color: light-dark(#767676, #8e8e93);
63
+ --border-color-hover: color-mix(in srgb, var(--border-color) 70%, black);
64
+ --border-color-active: color-mix(in srgb, var(--border-color) 90%, black);
65
+ --border-color-readonly: color-mix(
66
+ in srgb,
67
+ var(--border-color) 45%,
68
+ transparent
69
+ );
70
+ --border-color-disabled: var(--border-color-readonly);
71
+
72
+ --background-color: white;
73
+ --background-color-hover: color-mix(
74
+ in srgb,
75
+ var(--background-color) 95%,
76
+ black
77
+ );
78
+ --background-color-readonly: var(--background-color);
79
+ --background-color-disabled: color-mix(
80
+ in srgb,
81
+ var(--background-color) 60%,
82
+ transparent
83
+ );
84
+
85
+ --color: currentColor;
86
+ --color-readonly: color-mix(in srgb, currentColor 60%, transparent);
87
+ --color-disabled: var(--color-readonly);
88
+ color: var(--color);
89
+
90
+ background-color: var(--background-color);
91
+ border-width: var(--outer-width);
92
+ border-width: var(--outer-width);
93
+ border-style: solid;
94
+ border-color: transparent;
95
+ border-radius: var(--border-radius);
96
+ outline-width: var(--border-width);
97
+ outline-style: solid;
98
+ outline-color: var(--border-color);
99
+ outline-offset: calc(-1 * (var(--border-width)));
100
+ }
101
+ /* Focus */
102
+ .navi_input[data-focus] {
103
+ border-color: var(--outline-color);
104
+ outline-width: var(--outer-width);
105
+ outline-color: var(--outline-color);
106
+ outline-offset: calc(-1 * var(--outer-width));
107
+ }
108
+ /* Readonly */
109
+ .navi_input[data-readonly] {
110
+ color: var(--color-readonly);
111
+ background-color: var(--background-color-readonly);
112
+ outline-color: var(--border-color-readonly);
113
+ }
114
+ .navi_input[data-readonly]::placeholder {
115
+ color: var(--color-readonly);
116
+ }
117
+ /* Disabled */
118
+ .navi_input[data-disabled] {
119
+ color: var(--color-disabled);
120
+ background-color: var(--background-color-disabled);
121
+ outline-color: var(--border-color-disabled);
122
+ }
123
+ /* Invalid */
124
+ .navi_input[aria-invalid="true"] {
125
+ border-color: var(--invalid-color);
126
+ }
127
+ `;
128
+
50
129
  export const InputTextual = forwardRef((props, ref) => {
51
130
  const uiStateController = useUIStateController(props, "input");
52
131
  const uiState = useUIState(uiStateController);
@@ -83,7 +162,8 @@ const InputTextualBasic = forwardRef((props, ref) => {
83
162
  autoFocus,
84
163
  autoFocusVisible,
85
164
  autoSelect,
86
- appearance = "custom",
165
+ appearance = "navi",
166
+ accentColor,
87
167
  width,
88
168
  height,
89
169
  ...rest
@@ -110,14 +190,14 @@ const InputTextualBasic = forwardRef((props, ref) => {
110
190
  <input
111
191
  {...rest}
112
192
  ref={innerRef}
193
+ className={appearance === "navi" ? "navi_input" : undefined}
113
194
  type={type}
114
195
  data-value={uiState}
115
196
  value={innerValue}
116
- data-field=""
117
- data-field-with-border=""
118
- data-custom={appearance === "custom" ? "" : undefined}
119
197
  readOnly={innerReadOnly}
120
198
  disabled={innerDisabled}
199
+ data-readOnly={innerReadOnly ? "" : undefined}
200
+ data-disabled={innerDisabled ? "" : undefined}
121
201
  onInput={(e) => {
122
202
  let inputValue;
123
203
  if (type === "number") {
@@ -141,12 +221,23 @@ const InputTextualBasic = forwardRef((props, ref) => {
141
221
  />
142
222
  );
143
223
 
224
+ useLayoutEffect(() => {
225
+ return initCustomField(innerRef.current, innerRef.current);
226
+ }, []);
227
+
228
+ if (type === "hidden") {
229
+ return inputTextual;
230
+ }
144
231
  return (
145
232
  <LoadableInlineElement
146
233
  loading={innerLoading}
147
- color="light-dark(#355fcc, #3b82f6)"
234
+ style={{
235
+ "--accent-color": accentColor || "light-dark(#355fcc, #4476ff)",
236
+ }}
237
+ color="var(--accent-color)"
148
238
  width={width}
149
239
  height={height}
240
+ inset={-1}
150
241
  >
151
242
  {inputTextual}
152
243
  </LoadableInlineElement>
@@ -3,29 +3,41 @@ import { forwardRef } from "preact/compat";
3
3
  import { useImperativeHandle, useRef, useState } from "preact/hooks";
4
4
 
5
5
  import.meta.css = /* css */ `
6
- label[data-readonly] {
6
+ label {
7
+ cursor: pointer;
8
+ }
9
+
10
+ label[data-readonly],
11
+ label[data-disabled] {
7
12
  color: rgba(0, 0, 0, 0.5);
13
+ cursor: default;
8
14
  }
9
15
  `;
10
16
 
11
17
  export const ReportReadOnlyOnLabelContext = createContext();
18
+ export const ReportDisabledOnLabelContext = createContext();
12
19
 
13
20
  export const Label = forwardRef((props, ref) => {
14
- const { readOnly, children, ...rest } = props;
21
+ const { readOnly, disabled, children, ...rest } = props;
15
22
  const innerRef = useRef();
16
23
  useImperativeHandle(ref, () => innerRef.current);
17
24
 
18
25
  const [inputReadOnly, setInputReadOnly] = useState(false);
19
26
  const innerReadOnly = readOnly || inputReadOnly;
27
+ const [inputDisabled, setInputDisabled] = useState(false);
28
+ const innerDisabled = disabled || inputDisabled;
20
29
 
21
30
  return (
22
31
  <label
23
32
  ref={innerRef}
24
33
  data-readonly={innerReadOnly ? "" : undefined}
34
+ data-disabled={innerDisabled ? "" : undefined}
25
35
  {...rest}
26
36
  >
27
37
  <ReportReadOnlyOnLabelContext.Provider value={setInputReadOnly}>
28
- {children}
38
+ <ReportDisabledOnLabelContext.Provider value={setInputDisabled}>
39
+ {children}
40
+ </ReportDisabledOnLabelContext.Provider>
29
41
  </ReportReadOnlyOnLabelContext.Provider>
30
42
  </label>
31
43
  );
@@ -0,0 +1,8 @@
1
+ import.meta.css = /* css */ `
2
+ :root {
3
+ --navi-background-color-readonly: #d3d3d3;
4
+ --navi-color-readonly: grey;
5
+ --navi-background-color-disabled: #d3d3d3;
6
+ --navi-color-disabled: #eeeeee;
7
+ }
8
+ `;