@clicoh/orion-library 1.2.0-beta.10 → 1.2.0-beta.12
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.
- package/dist/components/01-atoms/CodeBlock/CodeBlock.d.ts +56 -0
- package/dist/components/01-atoms/CodeBlock/CodeBlock.d.ts.map +1 -0
- package/dist/components/01-atoms/CodeBlock/CodeBlock.jsx +97 -0
- package/dist/components/01-atoms/CodeBlock/CodeBlock.jsx.map +1 -0
- package/dist/components/01-atoms/CodeBlock/index.d.ts +2 -0
- package/dist/components/01-atoms/CodeBlock/index.d.ts.map +1 -0
- package/dist/components/01-atoms/CodeBlock/index.js +2 -0
- package/dist/components/01-atoms/CodeBlock/index.js.map +1 -0
- package/dist/components/01-atoms/Input/Input.d.ts +1 -1
- package/dist/components/01-atoms/Input/Input.d.ts.map +1 -1
- package/dist/components/01-atoms/Input/Input.jsx +5 -3
- package/dist/components/01-atoms/Input/Input.jsx.map +1 -1
- package/dist/components/01-atoms/Select/Select.d.ts +5 -1
- package/dist/components/01-atoms/Select/Select.d.ts.map +1 -1
- package/dist/components/01-atoms/Select/Select.jsx +51 -9
- package/dist/components/01-atoms/Select/Select.jsx.map +1 -1
- package/dist/components/01-atoms/Select/SelectList.d.ts +41 -0
- package/dist/components/01-atoms/Select/SelectList.d.ts.map +1 -0
- package/dist/components/01-atoms/Select/SelectList.jsx +116 -0
- package/dist/components/01-atoms/Select/SelectList.jsx.map +1 -0
- package/dist/components/01-atoms/Stat/Stat.d.ts +44 -0
- package/dist/components/01-atoms/Stat/Stat.d.ts.map +1 -0
- package/dist/components/01-atoms/Stat/Stat.jsx +60 -0
- package/dist/components/01-atoms/Stat/Stat.jsx.map +1 -0
- package/dist/components/01-atoms/Stat/index.d.ts +2 -0
- package/dist/components/01-atoms/Stat/index.d.ts.map +1 -0
- package/dist/components/01-atoms/Stat/index.js +2 -0
- package/dist/components/01-atoms/Stat/index.js.map +1 -0
- package/dist/components/01-atoms/index.d.ts +2 -0
- package/dist/components/01-atoms/index.d.ts.map +1 -1
- package/dist/components/01-atoms/index.js +2 -0
- package/dist/components/01-atoms/index.js.map +1 -1
- package/dist/components/02-molecules/Stepper/Stepper.d.ts +70 -0
- package/dist/components/02-molecules/Stepper/Stepper.d.ts.map +1 -0
- package/dist/components/02-molecules/Stepper/Stepper.jsx +204 -0
- package/dist/components/02-molecules/Stepper/Stepper.jsx.map +1 -0
- package/dist/components/02-molecules/Stepper/index.d.ts +2 -0
- package/dist/components/02-molecules/Stepper/index.d.ts.map +1 -0
- package/dist/components/02-molecules/Stepper/index.js +2 -0
- package/dist/components/02-molecules/Stepper/index.js.map +1 -0
- package/dist/components/02-molecules/Timeline/Timeline.d.ts +47 -0
- package/dist/components/02-molecules/Timeline/Timeline.d.ts.map +1 -0
- package/dist/components/02-molecules/Timeline/Timeline.jsx +65 -0
- package/dist/components/02-molecules/Timeline/Timeline.jsx.map +1 -0
- package/dist/components/02-molecules/Timeline/index.d.ts +2 -0
- package/dist/components/02-molecules/Timeline/index.d.ts.map +1 -0
- package/dist/components/02-molecules/Timeline/index.js +2 -0
- package/dist/components/02-molecules/Timeline/index.js.map +1 -0
- package/dist/components/02-molecules/index.d.ts +2 -0
- package/dist/components/02-molecules/index.d.ts.map +1 -1
- package/dist/components/02-molecules/index.js +2 -0
- package/dist/components/02-molecules/index.js.map +1 -1
- package/dist/components/03-organisms/MapView/MapView.d.ts +4 -1
- package/dist/components/03-organisms/MapView/MapView.d.ts.map +1 -1
- package/dist/components/03-organisms/MapView/MapView.jsx +13 -13
- package/dist/components/03-organisms/MapView/MapView.jsx.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
/** Inclusive range of line numbers, counted from `startLine`. */
|
|
3
|
+
export type CodeBlockRange = [from: number, to: number];
|
|
4
|
+
export type CodeBlockProps = {
|
|
5
|
+
/** The source to show, as plain text. */
|
|
6
|
+
code: string;
|
|
7
|
+
/** Accessible name and tooltip of the copy button. */
|
|
8
|
+
copyLabel: string;
|
|
9
|
+
/** Replaces `copyLabel` for a moment after copying, and is announced. */
|
|
10
|
+
copiedLabel: string;
|
|
11
|
+
/** Shown in the header (`ts`, `sql`, `diff`). No syntax coloring is applied. */
|
|
12
|
+
language?: string;
|
|
13
|
+
/** Number of the first line. Line numbers are shown only when it is set. */
|
|
14
|
+
startLine?: number;
|
|
15
|
+
/** Lines to emphasize, as inclusive ranges in the same numbering. */
|
|
16
|
+
highlight?: CodeBlockRange[];
|
|
17
|
+
/** Called when the browser refuses to write to the clipboard. */
|
|
18
|
+
onCopyError?: (error: unknown) => void;
|
|
19
|
+
} & Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
|
|
20
|
+
/**
|
|
21
|
+
* Read-only block of source code with a copy button. Shows an excerpt
|
|
22
|
+
* exactly as written: monospace, no wrapping, horizontal scroll when a line
|
|
23
|
+
* is longer than the block.
|
|
24
|
+
*
|
|
25
|
+
* Setting `startLine` numbers the lines, so an excerpt from the middle of a
|
|
26
|
+
* file keeps its real line numbers; `highlight` then marks ranges in that
|
|
27
|
+
* same numbering. There is no syntax coloring.
|
|
28
|
+
*
|
|
29
|
+
* Copying uses the Clipboard API, which browsers only expose on secure
|
|
30
|
+
* origins (`https` or `localhost`). When it fails the button stays as it was
|
|
31
|
+
* and `onCopyError` receives the reason.
|
|
32
|
+
*
|
|
33
|
+
* @component
|
|
34
|
+
* @example
|
|
35
|
+
* <CodeBlock
|
|
36
|
+
* code={excerpt}
|
|
37
|
+
* language="ts"
|
|
38
|
+
* startLine={940}
|
|
39
|
+
* highlight={[[943, 943]]}
|
|
40
|
+
* copyLabel="Copy code"
|
|
41
|
+
* copiedLabel="Copied"
|
|
42
|
+
* />
|
|
43
|
+
*
|
|
44
|
+
* @param {Object} props - The properties of the CodeBlock component.
|
|
45
|
+
* @param {string} props.code - The source to show, as plain text.
|
|
46
|
+
* @param {string} props.copyLabel - Accessible name and tooltip of the copy button.
|
|
47
|
+
* @param {string} props.copiedLabel - Shown and announced right after copying.
|
|
48
|
+
* @param {string} [props.language] - Label shown in the header.
|
|
49
|
+
* @param {number} [props.startLine] - Number of the first line; enables line numbers.
|
|
50
|
+
* @param {CodeBlockRange[]} [props.highlight=[]] - Inclusive line ranges to emphasize.
|
|
51
|
+
* @param {(error: unknown) => void} [props.onCopyError] - Called when the clipboard write fails.
|
|
52
|
+
*
|
|
53
|
+
* @returns {ReactNode} The rendered CodeBlock component.
|
|
54
|
+
*/
|
|
55
|
+
export declare function CodeBlock({ code, copyLabel, copiedLabel, language, startLine, highlight, onCopyError, ...restProps }: CodeBlockProps): ReactNode;
|
|
56
|
+
//# sourceMappingURL=CodeBlock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeBlock.d.ts","sourceRoot":"","sources":["../../../../src/components/01-atoms/CodeBlock/CodeBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAKf,iEAAiE;AACjE,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG;IAC3B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,CAAC;AAQrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,SAAS,EACT,WAAW,EACX,QAAQ,EACR,SAAS,EACT,SAAc,EACd,WAAW,EACX,GAAG,SAAS,EACb,EAAE,cAAc,GAAG,SAAS,CAgG5B"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { useEffect, useRef, useState, } from 'react';
|
|
4
|
+
import { FiCheck, FiCopy } from 'react-icons/fi';
|
|
5
|
+
import { Each } from '../../00-base';
|
|
6
|
+
import { IconButton } from '../IconButton';
|
|
7
|
+
const COPIED_FEEDBACK_MS = 1600;
|
|
8
|
+
function isHighlighted(line, ranges) {
|
|
9
|
+
return ranges.some(([from, to]) => line >= from && line <= to);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Read-only block of source code with a copy button. Shows an excerpt
|
|
13
|
+
* exactly as written: monospace, no wrapping, horizontal scroll when a line
|
|
14
|
+
* is longer than the block.
|
|
15
|
+
*
|
|
16
|
+
* Setting `startLine` numbers the lines, so an excerpt from the middle of a
|
|
17
|
+
* file keeps its real line numbers; `highlight` then marks ranges in that
|
|
18
|
+
* same numbering. There is no syntax coloring.
|
|
19
|
+
*
|
|
20
|
+
* Copying uses the Clipboard API, which browsers only expose on secure
|
|
21
|
+
* origins (`https` or `localhost`). When it fails the button stays as it was
|
|
22
|
+
* and `onCopyError` receives the reason.
|
|
23
|
+
*
|
|
24
|
+
* @component
|
|
25
|
+
* @example
|
|
26
|
+
* <CodeBlock
|
|
27
|
+
* code={excerpt}
|
|
28
|
+
* language="ts"
|
|
29
|
+
* startLine={940}
|
|
30
|
+
* highlight={[[943, 943]]}
|
|
31
|
+
* copyLabel="Copy code"
|
|
32
|
+
* copiedLabel="Copied"
|
|
33
|
+
* />
|
|
34
|
+
*
|
|
35
|
+
* @param {Object} props - The properties of the CodeBlock component.
|
|
36
|
+
* @param {string} props.code - The source to show, as plain text.
|
|
37
|
+
* @param {string} props.copyLabel - Accessible name and tooltip of the copy button.
|
|
38
|
+
* @param {string} props.copiedLabel - Shown and announced right after copying.
|
|
39
|
+
* @param {string} [props.language] - Label shown in the header.
|
|
40
|
+
* @param {number} [props.startLine] - Number of the first line; enables line numbers.
|
|
41
|
+
* @param {CodeBlockRange[]} [props.highlight=[]] - Inclusive line ranges to emphasize.
|
|
42
|
+
* @param {(error: unknown) => void} [props.onCopyError] - Called when the clipboard write fails.
|
|
43
|
+
*
|
|
44
|
+
* @returns {ReactNode} The rendered CodeBlock component.
|
|
45
|
+
*/
|
|
46
|
+
export function CodeBlock({ code, copyLabel, copiedLabel, language, startLine, highlight = [], onCopyError, ...restProps }) {
|
|
47
|
+
const [isCopied, setIsCopied] = useState(false);
|
|
48
|
+
const resetTimer = useRef(undefined);
|
|
49
|
+
useEffect(() => () => clearTimeout(resetTimer.current), []);
|
|
50
|
+
const lines = code.replace(/\n$/, '').split('\n');
|
|
51
|
+
const isNumbered = startLine !== undefined;
|
|
52
|
+
const firstLine = startLine ?? 1;
|
|
53
|
+
const gutterWidth = `${String(firstLine + lines.length - 1).length}ch`;
|
|
54
|
+
const copy = async () => {
|
|
55
|
+
try {
|
|
56
|
+
await navigator.clipboard.writeText(code);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
onCopyError?.(error);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
setIsCopied(true);
|
|
63
|
+
clearTimeout(resetTimer.current);
|
|
64
|
+
resetTimer.current = setTimeout(() => setIsCopied(false), COPIED_FEEDBACK_MS);
|
|
65
|
+
};
|
|
66
|
+
return (<div {...restProps} className={clsx('border-gray-5 bg-gray-7 dark:border-gray-1 dark:bg-black-1 min-w-0 overflow-hidden rounded-lg border', restProps.className)}>
|
|
67
|
+
<div className="border-gray-5 dark:border-gray-1 flex items-center justify-between gap-2 border-b py-1 pr-1 pl-3">
|
|
68
|
+
<span className="text-gray-1 dark:text-gray-2 truncate text-xs leading-4">
|
|
69
|
+
{language}
|
|
70
|
+
</span>
|
|
71
|
+
<IconButton icon={isCopied ? <FiCheck /> : <FiCopy />} label={isCopied ? copiedLabel : copyLabel} onClick={copy}/>
|
|
72
|
+
<span role="status" className="sr-only">
|
|
73
|
+
{isCopied ? copiedLabel : ''}
|
|
74
|
+
</span>
|
|
75
|
+
</div>
|
|
76
|
+
<pre tabIndex={0} className="focus-visible:ring-lavender dark:focus-visible:ring-lavender-dark m-0 overflow-x-auto py-2 font-mono text-xs leading-5 text-black focus-visible:ring-2 focus-visible:outline-none focus-visible:ring-inset dark:text-white">
|
|
77
|
+
<code className="block min-w-max">
|
|
78
|
+
<Each of={lines} render={(line, index) => {
|
|
79
|
+
const number = firstLine + index;
|
|
80
|
+
const isMarked = isHighlighted(number, highlight);
|
|
81
|
+
return (<span className={clsx('flex', isMarked && 'bg-lavender-2 dark:bg-lavender-dark-1')}>
|
|
82
|
+
{isNumbered && (<span aria-hidden="true" style={{ width: gutterWidth }} className={clsx('box-content shrink-0 px-3 text-right select-none', isMarked
|
|
83
|
+
? 'text-lavender dark:text-lavender-dark font-semibold'
|
|
84
|
+
: 'text-gray-1 dark:text-gray-2')}>
|
|
85
|
+
{number}
|
|
86
|
+
</span>)}
|
|
87
|
+
<span className={clsx('pr-3 whitespace-pre', !isNumbered && 'pl-3')}>
|
|
88
|
+
{line || ' '}
|
|
89
|
+
</span>
|
|
90
|
+
{'\n'}
|
|
91
|
+
</span>);
|
|
92
|
+
}}/>
|
|
93
|
+
</code>
|
|
94
|
+
</pre>
|
|
95
|
+
</div>);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=CodeBlock.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeBlock.jsx","sourceRoot":"","sources":["../../../../src/components/01-atoms/CodeBlock/CodeBlock.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAGL,SAAS,EACT,MAAM,EACN,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAsB3C,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,SAAS,aAAa,CAAC,IAAY,EAAE,MAAwB;IAC3D,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,IAAI,EACJ,SAAS,EACT,WAAW,EACX,QAAQ,EACR,SAAS,EACT,SAAS,GAAG,EAAE,EACd,WAAW,EACX,GAAG,SAAS,EACG;IACf,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,MAAM,CAAgC,SAAS,CAAC,CAAC;IAEpE,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAE5D,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,SAAS,KAAK,SAAS,CAAC;IAC3C,MAAM,SAAS,GAAG,SAAS,IAAI,CAAC,CAAC;IACjC,MAAM,WAAW,GAAG,GAAG,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC;IAEvE,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;QACrC,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACjC,UAAU,CAAC,OAAO,GAAG,UAAU,CAC7B,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EACxB,kBAAkB,CACnB,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,CAAC,GAAG,CACF,IAAI,SAAS,CAAC,CACd,SAAS,CAAC,CAAC,IAAI,CACb,sGAAsG,EACtG,SAAS,CAAC,SAAS,CACpB,CAAC,CAEF;MAAA,CAAC,GAAG,CAAC,SAAS,CAAC,kGAAkG,CAC/G;QAAA,CAAC,IAAI,CAAC,SAAS,CAAC,yDAAyD,CACvE;UAAA,CAAC,QAAQ,CACX;QAAA,EAAE,IAAI,CACN;QAAA,CAAC,UAAU,CACT,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,AAAD,EAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,AAAD,EAAG,CAAC,CAC1C,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAC1C,OAAO,CAAC,CAAC,IAAI,CAAC,EAEhB;QAAA,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,CACrC;UAAA,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAC9B;QAAA,EAAE,IAAI,CACR;MAAA,EAAE,GAAG,CACL;MAAA,CAAC,GAAG,CACF,QAAQ,CAAC,CAAC,CAAC,CAAC,CACZ,SAAS,CAAC,4NAA4N,CAEtO;QAAA,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAC/B;UAAA,CAAC,IAAI,CACH,EAAE,CAAC,CAAC,KAAK,CAAC,CACV,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YACtB,MAAM,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC;YACjC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAElD,OAAO,CACL,CAAC,IAAI,CACH,SAAS,CAAC,CAAC,IAAI,CACb,MAAM,EACN,QAAQ,IAAI,uCAAuC,CACpD,CAAC,CAEF;kBAAA,CAAC,UAAU,IAAI,CACb,CAAC,IAAI,CACH,WAAW,CAAC,MAAM,CAClB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAC9B,SAAS,CAAC,CAAC,IAAI,CACb,kDAAkD,EAClD,QAAQ;wBACN,CAAC,CAAC,qDAAqD;wBACvD,CAAC,CAAC,8BAA8B,CACnC,CAAC,CAEF;sBAAA,CAAC,MAAM,CACT;oBAAA,EAAE,IAAI,CAAC,CACR,CACD;kBAAA,CAAC,IAAI,CACH,SAAS,CAAC,CAAC,IAAI,CACb,qBAAqB,EACrB,CAAC,UAAU,IAAI,MAAM,CACtB,CAAC,CAEF;oBAAA,CAAC,IAAI,IAAI,GAAG,CACd;kBAAA,EAAE,IAAI,CACN;kBAAA,CAAC,IAAI,CACP;gBAAA,EAAE,IAAI,CAAC,CACR,CAAC;QACJ,CAAC,CAAC,EAEN;QAAA,EAAE,IAAI,CACR;MAAA,EAAE,GAAG,CACP;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/01-atoms/CodeBlock/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/01-atoms/CodeBlock/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -38,7 +38,7 @@ type InputProps = {
|
|
|
38
38
|
* @param {ReactNode} [props.iconR] - Optional icon to be displayed to the right of the input field.
|
|
39
39
|
* @param {boolean} [props.isMutedWhenEmpty] - Renders the border and label in gray while the field has no value.
|
|
40
40
|
* @param {boolean} [props.hideLabel] - Keeps the label for assistive technology only and drops the floating label and its border notch. Use it when a heading outside the field already names it.
|
|
41
|
-
* @param {string} [props.placeholder] - Placeholder shown inside the field.
|
|
41
|
+
* @param {string} [props.placeholder] - Placeholder shown inside the field. With `hideLabel` it is always visible; with the floating label it only appears while the field is focused, once the label has moved out of the way.
|
|
42
42
|
*
|
|
43
43
|
* @returns {ReactNode} The rendered Input component.
|
|
44
44
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../../src/components/01-atoms/Input/Input.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AAKf,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,IAAI,EAAE,IAAI,CACR,iBAAiB,CACf,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,gBAAgB,CACjB,CAAC,MAAM,CAAC,EACT,QAAQ,GAAG,UAAU,GAAG,OAAO,CAChC,CAAC;KACH,GAAG,IAAI,CACN,iBAAiB,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,EAC1E,aAAa,CACd,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,KAAK,EACL,UAAU,EACV,KAAK,EACL,KAAK,EACL,KAAK,EACL,gBAAgB,EAChB,SAAiB,EACjB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,GACtB,EAAE,UAAU,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../../src/components/01-atoms/Input/Input.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AAKf,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,IAAI,EAAE,IAAI,CACR,iBAAiB,CACf,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,gBAAgB,CACjB,CAAC,MAAM,CAAC,EACT,QAAQ,GAAG,UAAU,GAAG,OAAO,CAChC,CAAC;KACH,GAAG,IAAI,CACN,iBAAiB,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,EAC1E,aAAa,CACd,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,KAAK,EACL,UAAU,EACV,KAAK,EACL,KAAK,EACL,KAAK,EACL,gBAAgB,EAChB,SAAiB,EACjB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,GACtB,EAAE,UAAU,GAAG,SAAS,CA6GxB"}
|
|
@@ -28,7 +28,7 @@ import { RenderErrorOrHelperText } from './utils/RenderErrorOrHelperText';
|
|
|
28
28
|
* @param {ReactNode} [props.iconR] - Optional icon to be displayed to the right of the input field.
|
|
29
29
|
* @param {boolean} [props.isMutedWhenEmpty] - Renders the border and label in gray while the field has no value.
|
|
30
30
|
* @param {boolean} [props.hideLabel] - Keeps the label for assistive technology only and drops the floating label and its border notch. Use it when a heading outside the field already names it.
|
|
31
|
-
* @param {string} [props.placeholder] - Placeholder shown inside the field.
|
|
31
|
+
* @param {string} [props.placeholder] - Placeholder shown inside the field. With `hideLabel` it is always visible; with the floating label it only appears while the field is focused, once the label has moved out of the way.
|
|
32
32
|
*
|
|
33
33
|
* @returns {ReactNode} The rendered Input component.
|
|
34
34
|
*/
|
|
@@ -41,7 +41,9 @@ export function Input({ label, input, helperText, error, iconL, iconR, isMutedWh
|
|
|
41
41
|
undefined;
|
|
42
42
|
const isPassword = input.type === 'password';
|
|
43
43
|
const effectiveType = isPassword && showPassword ? 'text' : input.type;
|
|
44
|
-
const inputClasses = clsx('peer disabled:text-gray-3 dark:disabled:text-gray-2 h-full w-full rounded-full bg-transparent text-sm font-normal text-black outline-0 transition-all focus:text-black dark:bg-black dark:text-white dark:focus:text-white', iconL ? 'pr-5 pl-11' : 'px-5', hideLabel
|
|
44
|
+
const inputClasses = clsx('peer disabled:text-gray-3 dark:disabled:text-gray-2 h-full w-full rounded-full bg-transparent text-sm font-normal text-black outline-0 transition-all focus:text-black dark:bg-black dark:text-white dark:focus:text-white', iconL ? 'pr-5 pl-11' : 'px-5', hideLabel
|
|
45
|
+
? 'placeholder:text-gray-2 dark:placeholder:text-gray-2'
|
|
46
|
+
: 'focus:placeholder:text-gray-2 dark:focus:placeholder:text-gray-2 placeholder:text-transparent', input.className);
|
|
45
47
|
const { labelProps, legendClasses, fieldsetClasses } = generateBorder(error, {
|
|
46
48
|
isMutedWhenEmpty,
|
|
47
49
|
hideLabel,
|
|
@@ -55,7 +57,7 @@ export function Input({ label, input, helperText, error, iconL, iconR, isMutedWh
|
|
|
55
57
|
</button>) : (iconR);
|
|
56
58
|
return (<div className="w-full max-w-full">
|
|
57
59
|
<div className="relative h-9">
|
|
58
|
-
<input {...input} id={id} type={effectiveType} className={inputClasses} placeholder={
|
|
60
|
+
<input {...input} id={id} type={effectiveType} className={inputClasses} placeholder={placeholder || ' '} aria-invalid={error ? true : input['aria-invalid']} aria-describedby={describedBy}/>
|
|
59
61
|
{hideLabel ? (<label htmlFor={id} className="sr-only">
|
|
60
62
|
{label}
|
|
61
63
|
</label>) : (<label {...labelProps}>{label}</label>)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.jsx","sourceRoot":"","sources":["../../../../src/components/01-atoms/Input/Input.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAIL,KAAK,EACL,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AA2B1E;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,KAAK,CAAC,EACpB,KAAK,EACL,KAAK,EACL,UAAU,EACV,KAAK,EACL,KAAK,EACL,KAAK,EACL,gBAAgB,EAChB,SAAS,GAAG,KAAK,EACjB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,GACV;IACX,MAAM,WAAW,GAAG,KAAK,EAAE,CAAC;IAC5B,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,IAAI,WAAW,CAAC;IACnC,MAAM,aAAa,GAAG,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,MAAM,WAAW,GACf,CAAC,KAAK,CAAC,kBAAkB,CAAC,EAAE,aAAa,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACpE,SAAS,CAAC;IAEZ,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;IAC7C,MAAM,aAAa,GAAG,UAAU,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;IAEvE,MAAM,YAAY,GAAG,IAAI,CACvB,4NAA4N,EAC5N,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,EAC7B,SAAS,
|
|
1
|
+
{"version":3,"file":"Input.jsx","sourceRoot":"","sources":["../../../../src/components/01-atoms/Input/Input.tsx"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ type SelectProps = {
|
|
|
8
8
|
readonly error?: string;
|
|
9
9
|
readonly isMutedWhenEmpty?: boolean;
|
|
10
10
|
readonly hideLabel?: boolean;
|
|
11
|
+
readonly labelAddon?: ReactNode;
|
|
12
|
+
readonly customList?: boolean;
|
|
11
13
|
};
|
|
12
14
|
/**
|
|
13
15
|
* Select component for rendering a dropdown with customizable options, labels, helper text, and error messages.
|
|
@@ -33,9 +35,11 @@ type SelectProps = {
|
|
|
33
35
|
* @param {string} [props.error] - Optional error message to be displayed below the select dropdown.
|
|
34
36
|
* @param {boolean} [props.isMutedWhenEmpty] - Renders the border and label in gray while no option is selected.
|
|
35
37
|
* @param {boolean} [props.hideLabel] - Keeps the label for assistive technology only and drops the floating label and its border notch. Use it when a heading outside the field already names it; pair it with `placeholder`.
|
|
38
|
+
* @param {ReactNode} [props.labelAddon] - Element rendered right after the floating label, inside the border notch — typically an info icon wrapped in a `Tooltip`. It stays interactive and is not part of the label's accessible name. Ignored with `hideLabel`.
|
|
39
|
+
* @param {boolean} [props.customList=false] - Opens Orion's own option list instead of the native popup, which each browser and OS paints its own way. Same `options`, `select.value` and `select.onChange`: picking an option fires the native `change` event.
|
|
36
40
|
*
|
|
37
41
|
* @returns {ReactNode} The rendered Select component.
|
|
38
42
|
*/
|
|
39
|
-
export declare function Select({ label, options, select, placeholder, helperText, error, isMutedWhenEmpty, hideLabel, }: SelectProps): ReactNode;
|
|
43
|
+
export declare function Select({ label, options, select, placeholder, helperText, error, isMutedWhenEmpty, hideLabel, labelAddon, customList, }: SelectProps): ReactNode;
|
|
40
44
|
export {};
|
|
41
45
|
//# sourceMappingURL=Select.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../../src/components/01-atoms/Select/Select.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,oBAAoB,
|
|
1
|
+
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../../src/components/01-atoms/Select/Select.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,oBAAoB,EAI1B,MAAM,OAAO,CAAC;AAOf,KAAK,WAAW,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CACpB,iBAAiB,CACf,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,iBAAiB,CAClB,EACD,UAAU,CACX,CAAC;IACF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,OAAO,EACP,MAAM,EACN,WAAW,EACX,UAAU,EACV,KAAK,EACL,gBAAgB,EAChB,SAAiB,EACjB,UAAU,EACV,UAAkB,GACnB,EAAE,WAAW,GAAG,SAAS,CAqJzB"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import { useId, } from 'react';
|
|
3
|
+
import { useId, useRef, useState, } from 'react';
|
|
4
4
|
import { FaSortDown } from 'react-icons/fa';
|
|
5
|
-
import { Each } from '../../00-base';
|
|
5
|
+
import { Each, Show } from '../../00-base';
|
|
6
6
|
import { generateBorder } from '../Input/utils/border';
|
|
7
7
|
import { RenderErrorOrHelperText } from '../Input/utils/RenderErrorOrHelperText';
|
|
8
|
+
import { SelectList } from './SelectList';
|
|
8
9
|
/**
|
|
9
10
|
* Select component for rendering a dropdown with customizable options, labels, helper text, and error messages.
|
|
10
11
|
*
|
|
@@ -29,10 +30,12 @@ import { RenderErrorOrHelperText } from '../Input/utils/RenderErrorOrHelperText'
|
|
|
29
30
|
* @param {string} [props.error] - Optional error message to be displayed below the select dropdown.
|
|
30
31
|
* @param {boolean} [props.isMutedWhenEmpty] - Renders the border and label in gray while no option is selected.
|
|
31
32
|
* @param {boolean} [props.hideLabel] - Keeps the label for assistive technology only and drops the floating label and its border notch. Use it when a heading outside the field already names it; pair it with `placeholder`.
|
|
33
|
+
* @param {ReactNode} [props.labelAddon] - Element rendered right after the floating label, inside the border notch — typically an info icon wrapped in a `Tooltip`. It stays interactive and is not part of the label's accessible name. Ignored with `hideLabel`.
|
|
34
|
+
* @param {boolean} [props.customList=false] - Opens Orion's own option list instead of the native popup, which each browser and OS paints its own way. Same `options`, `select.value` and `select.onChange`: picking an option fires the native `change` event.
|
|
32
35
|
*
|
|
33
36
|
* @returns {ReactNode} The rendered Select component.
|
|
34
37
|
*/
|
|
35
|
-
export function Select({ label, options, select, placeholder, helperText, error, isMutedWhenEmpty, hideLabel = false, }) {
|
|
38
|
+
export function Select({ label, options, select, placeholder, helperText, error, isMutedWhenEmpty, hideLabel = false, labelAddon, customList = false, }) {
|
|
36
39
|
const generatedId = useId();
|
|
37
40
|
const id = select?.id ?? generatedId;
|
|
38
41
|
const descriptionId = error || helperText ? `${id}-description` : undefined;
|
|
@@ -41,6 +44,22 @@ export function Select({ label, options, select, placeholder, helperText, error,
|
|
|
41
44
|
const selectProps = !select || !Object.hasOwn(select, 'value')
|
|
42
45
|
? { ...select, defaultValue: '' }
|
|
43
46
|
: select;
|
|
47
|
+
const selectRef = useRef(null);
|
|
48
|
+
const isControlled = Boolean(select && Object.hasOwn(select, 'value'));
|
|
49
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(String(selectProps.defaultValue ?? ''));
|
|
50
|
+
const currentValue = isControlled
|
|
51
|
+
? String(selectProps.value ?? '')
|
|
52
|
+
: uncontrolledValue;
|
|
53
|
+
const labelId = `${id}-label`;
|
|
54
|
+
const chooseFromList = (value) => {
|
|
55
|
+
const element = selectRef.current;
|
|
56
|
+
if (!element || element.value === value)
|
|
57
|
+
return;
|
|
58
|
+
element.value = value;
|
|
59
|
+
element.dispatchEvent(new Event('change', { bubbles: true }));
|
|
60
|
+
if (!isControlled)
|
|
61
|
+
setUncontrolledValue(value);
|
|
62
|
+
};
|
|
44
63
|
const isMuted = Boolean(isMutedWhenEmpty && !selectProps.value && !selectProps.defaultValue);
|
|
45
64
|
const selectClasses = clsx('peer disabled:text-gray-3 dark:disabled:text-gray-2 h-full w-full appearance-none rounded-full border border-none bg-transparent px-5 text-sm font-normal outline-0 transition-all dark:bg-black', isMuted ? 'text-gray-2 dark:text-gray-2' : 'text-black dark:text-white', select?.className);
|
|
46
65
|
const { labelProps, legendClasses, fieldsetClasses } = generateBorder(error, {
|
|
@@ -50,7 +69,7 @@ export function Select({ label, options, select, placeholder, helperText, error,
|
|
|
50
69
|
labelProps.htmlFor = id;
|
|
51
70
|
return (<div className="w-full max-w-full">
|
|
52
71
|
<div className="relative h-9">
|
|
53
|
-
<select {...selectProps} id={id} className={selectClasses} aria-invalid={error ? true : select?.['aria-invalid']} aria-describedby={describedBy}>
|
|
72
|
+
<select {...selectProps} ref={selectRef} id={id} tabIndex={customList ? -1 : selectProps.tabIndex} aria-hidden={customList || undefined} className={clsx(selectClasses, customList && 'pointer-events-none')} aria-invalid={error ? true : select?.['aria-invalid']} aria-describedby={describedBy}>
|
|
54
73
|
{!!placeholder && (<option value="" disabled hidden className="bg-white text-black dark:bg-black dark:text-white">
|
|
55
74
|
{placeholder}
|
|
56
75
|
</option>)}
|
|
@@ -58,16 +77,39 @@ export function Select({ label, options, select, placeholder, helperText, error,
|
|
|
58
77
|
{text}
|
|
59
78
|
</option>)}/>
|
|
60
79
|
</select>
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
80
|
+
{customList && (<SelectList id={id} labelId={labelId} options={Object.entries(options)} value={currentValue} disabled={select?.disabled} invalid={Boolean(error)} describedBy={describedBy} onChoose={chooseFromList}/>)}
|
|
81
|
+
<Show>
|
|
82
|
+
<Show.When isTrue={hideLabel}>
|
|
83
|
+
<label id={labelId} htmlFor={id} className="sr-only">
|
|
84
|
+
{label}
|
|
85
|
+
</label>
|
|
86
|
+
</Show.When>
|
|
87
|
+
<Show.When isTrue={Boolean(labelAddon)}>
|
|
88
|
+
<div className={clsx(labelProps.className, 'flex items-center gap-1')}>
|
|
89
|
+
<label id={labelId} htmlFor={id}>
|
|
90
|
+
{label}
|
|
91
|
+
</label>
|
|
92
|
+
<span className="pointer-events-auto flex">{labelAddon}</span>
|
|
93
|
+
</div>
|
|
94
|
+
</Show.When>
|
|
95
|
+
<Show.Else>
|
|
96
|
+
<label {...labelProps} id={labelId}>
|
|
97
|
+
{label}
|
|
98
|
+
</label>
|
|
99
|
+
</Show.Else>
|
|
100
|
+
</Show>
|
|
101
|
+
<FaSortDown aria-hidden="true" className={clsx('peer-disabled:text-gray-3 dark:peer-disabled:text-gray-2 pointer-events-none absolute top-2 right-4', error
|
|
65
102
|
? 'text-error dark:text-error-dark'
|
|
66
103
|
: isMuted
|
|
67
104
|
? 'text-gray-2 dark:text-gray-2'
|
|
68
105
|
: 'text-black dark:text-white')}/>
|
|
69
106
|
<fieldset className={fieldsetClasses}>
|
|
70
|
-
{!hideLabel && <legend className={legendClasses}>
|
|
107
|
+
{!hideLabel && (<legend className={legendClasses}>
|
|
108
|
+
{label}
|
|
109
|
+
{labelAddon && (<span aria-hidden="true" className="ml-1 inline-flex">
|
|
110
|
+
{labelAddon}
|
|
111
|
+
</span>)}
|
|
112
|
+
</legend>)}
|
|
71
113
|
</fieldset>
|
|
72
114
|
</div>
|
|
73
115
|
<RenderErrorOrHelperText id={descriptionId} disabled={select?.disabled} helperText={helperText} error={error} className="pl-6"/>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.jsx","sourceRoot":"","sources":["../../../../src/components/01-atoms/Select/Select.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAIL,KAAK,
|
|
1
|
+
{"version":3,"file":"Select.jsx","sourceRoot":"","sources":["../../../../src/components/01-atoms/Select/Select.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
type SelectListProps = {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly labelId: string;
|
|
5
|
+
readonly options: [string, string][];
|
|
6
|
+
readonly value: string;
|
|
7
|
+
readonly disabled?: boolean;
|
|
8
|
+
readonly invalid?: boolean;
|
|
9
|
+
readonly describedBy?: string;
|
|
10
|
+
readonly onChoose: (value: string) => void;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* SelectList draws the option list of a `Select` with `customList`, in place of the
|
|
14
|
+
* native popup the browser and the OS paint. A transparent button covers the field and
|
|
15
|
+
* owns focus and keyboard; the native `<select>` underneath keeps the value.
|
|
16
|
+
*
|
|
17
|
+
* @component
|
|
18
|
+
* @example
|
|
19
|
+
* <SelectList
|
|
20
|
+
* id="hour-list"
|
|
21
|
+
* labelId="hour-label"
|
|
22
|
+
* options={[['08:00', '08:00'], ['08:30', '08:30']]}
|
|
23
|
+
* value="08:00"
|
|
24
|
+
* onChoose={(value) => console.log(value)}
|
|
25
|
+
* />
|
|
26
|
+
*
|
|
27
|
+
* @param {SelectListProps} props - The properties of the SelectList component.
|
|
28
|
+
* @param {string} props.id - Base id for the listbox and its options.
|
|
29
|
+
* @param {string} props.labelId - Id of the visible label, which names the trigger.
|
|
30
|
+
* @param {[string, string][]} props.options - Value and text of each option, in order.
|
|
31
|
+
* @param {string} props.value - Value currently selected.
|
|
32
|
+
* @param {boolean} [props.disabled] - Disables the trigger.
|
|
33
|
+
* @param {boolean} [props.invalid] - Marks the trigger as invalid for assistive technology.
|
|
34
|
+
* @param {string} [props.describedBy] - Id of the helper or error text.
|
|
35
|
+
* @param {(value: string) => void} props.onChoose - Fired with the value the user picks.
|
|
36
|
+
*
|
|
37
|
+
* @returns {ReactNode} The trigger and, while open, the option list.
|
|
38
|
+
*/
|
|
39
|
+
export declare function SelectList({ id, labelId, options, value, disabled, invalid, describedBy, onChoose, }: SelectListProps): ReactNode;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=SelectList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectList.d.ts","sourceRoot":"","sources":["../../../../src/components/01-atoms/Select/SelectList.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAGf,KAAK,eAAe,GAAG;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C,CAAC;AAOF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,UAAU,CAAC,EACzB,EAAE,EACF,OAAO,EACP,OAAO,EACP,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAW,EACX,QAAQ,GACT,EAAE,eAAe,GAAG,SAAS,CAgI7B"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { useEffect, useRef, useState, } from 'react';
|
|
4
|
+
import { Each } from '../../00-base';
|
|
5
|
+
const listClasses = clsx('absolute top-full left-0 z-40 mt-1 max-h-[200px] min-w-full overflow-y-auto rounded-sm border py-1 shadow-md', 'border-gray-5 dark:border-gray-1 dark:bg-black-1 bg-white text-black dark:text-white');
|
|
6
|
+
/**
|
|
7
|
+
* SelectList draws the option list of a `Select` with `customList`, in place of the
|
|
8
|
+
* native popup the browser and the OS paint. A transparent button covers the field and
|
|
9
|
+
* owns focus and keyboard; the native `<select>` underneath keeps the value.
|
|
10
|
+
*
|
|
11
|
+
* @component
|
|
12
|
+
* @example
|
|
13
|
+
* <SelectList
|
|
14
|
+
* id="hour-list"
|
|
15
|
+
* labelId="hour-label"
|
|
16
|
+
* options={[['08:00', '08:00'], ['08:30', '08:30']]}
|
|
17
|
+
* value="08:00"
|
|
18
|
+
* onChoose={(value) => console.log(value)}
|
|
19
|
+
* />
|
|
20
|
+
*
|
|
21
|
+
* @param {SelectListProps} props - The properties of the SelectList component.
|
|
22
|
+
* @param {string} props.id - Base id for the listbox and its options.
|
|
23
|
+
* @param {string} props.labelId - Id of the visible label, which names the trigger.
|
|
24
|
+
* @param {[string, string][]} props.options - Value and text of each option, in order.
|
|
25
|
+
* @param {string} props.value - Value currently selected.
|
|
26
|
+
* @param {boolean} [props.disabled] - Disables the trigger.
|
|
27
|
+
* @param {boolean} [props.invalid] - Marks the trigger as invalid for assistive technology.
|
|
28
|
+
* @param {string} [props.describedBy] - Id of the helper or error text.
|
|
29
|
+
* @param {(value: string) => void} props.onChoose - Fired with the value the user picks.
|
|
30
|
+
*
|
|
31
|
+
* @returns {ReactNode} The trigger and, while open, the option list.
|
|
32
|
+
*/
|
|
33
|
+
export function SelectList({ id, labelId, options, value, disabled, invalid, describedBy, onChoose, }) {
|
|
34
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
35
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
36
|
+
const rootRef = useRef(null);
|
|
37
|
+
const listRef = useRef(null);
|
|
38
|
+
const listboxId = `${id}-listbox`;
|
|
39
|
+
const selectedIndex = options.findIndex(([optionValue]) => optionValue === value);
|
|
40
|
+
const open = () => {
|
|
41
|
+
setActiveIndex(Math.max(selectedIndex, 0));
|
|
42
|
+
setIsOpen(true);
|
|
43
|
+
};
|
|
44
|
+
const close = () => {
|
|
45
|
+
setIsOpen(false);
|
|
46
|
+
setActiveIndex(-1);
|
|
47
|
+
};
|
|
48
|
+
const choose = (index) => {
|
|
49
|
+
const option = options[index];
|
|
50
|
+
if (option)
|
|
51
|
+
onChoose(option[0]);
|
|
52
|
+
close();
|
|
53
|
+
};
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (!isOpen)
|
|
56
|
+
return;
|
|
57
|
+
const handleOutsideClick = (event) => {
|
|
58
|
+
if (rootRef.current && !rootRef.current.contains(event.target)) {
|
|
59
|
+
close();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
document.addEventListener('mousedown', handleOutsideClick);
|
|
63
|
+
return () => document.removeEventListener('mousedown', handleOutsideClick);
|
|
64
|
+
}, [isOpen]);
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (!isOpen || activeIndex < 0)
|
|
67
|
+
return;
|
|
68
|
+
listRef.current
|
|
69
|
+
?.querySelector(`#${CSS.escape(`${listboxId}-${activeIndex}`)}`)
|
|
70
|
+
?.scrollIntoView({ block: 'nearest' });
|
|
71
|
+
}, [isOpen, activeIndex, listboxId]);
|
|
72
|
+
const handleKeyDown = (event) => {
|
|
73
|
+
const last = options.length - 1;
|
|
74
|
+
if (!isOpen) {
|
|
75
|
+
if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(event.key)) {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
open();
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const moves = {
|
|
82
|
+
ArrowDown: Math.min(activeIndex + 1, last),
|
|
83
|
+
ArrowUp: Math.max(activeIndex - 1, 0),
|
|
84
|
+
Home: 0,
|
|
85
|
+
End: last,
|
|
86
|
+
};
|
|
87
|
+
if (event.key in moves) {
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
setActiveIndex(moves[event.key]);
|
|
90
|
+
}
|
|
91
|
+
else if (event.key === 'Enter' || event.key === ' ') {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
choose(activeIndex);
|
|
94
|
+
}
|
|
95
|
+
else if (event.key === 'Escape') {
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
close();
|
|
98
|
+
}
|
|
99
|
+
else if (event.key === 'Tab') {
|
|
100
|
+
close();
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
return (<div ref={rootRef} className="absolute inset-0">
|
|
104
|
+
<button type="button" disabled={disabled} aria-haspopup="listbox" aria-expanded={isOpen} aria-controls={listboxId} aria-labelledby={`${labelId} ${id}-value`} aria-describedby={describedBy} aria-invalid={invalid} aria-activedescendant={isOpen && activeIndex >= 0 ? `${listboxId}-${activeIndex}` : undefined} onClick={() => (isOpen ? close() : open())} onKeyDown={handleKeyDown} className="h-full w-full cursor-pointer rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-black/20 disabled:cursor-not-allowed dark:focus-visible:ring-white/30">
|
|
105
|
+
<span id={`${id}-value`} className="sr-only">
|
|
106
|
+
{selectedIndex >= 0 ? options[selectedIndex][1] : ''}
|
|
107
|
+
</span>
|
|
108
|
+
</button>
|
|
109
|
+
{isOpen && (<ul ref={listRef} id={listboxId} role="listbox" aria-labelledby={labelId} className={listClasses}>
|
|
110
|
+
<Each of={options} render={([optionValue, text], index) => (<li key={optionValue} id={`${listboxId}-${index}`} role="option" aria-selected={index === selectedIndex} onMouseEnter={() => setActiveIndex(index)} onMouseDown={(event) => event.preventDefault()} onClick={() => choose(index)} className={clsx('cursor-pointer px-3 py-2 text-sm whitespace-nowrap', index === activeIndex && 'bg-gray-6 dark:bg-gray-1', index === selectedIndex && 'font-semibold')}>
|
|
111
|
+
{text}
|
|
112
|
+
</li>)}/>
|
|
113
|
+
</ul>)}
|
|
114
|
+
</div>);
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=SelectList.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectList.jsx","sourceRoot":"","sources":["../../../../src/components/01-atoms/Select/SelectList.tsx"],"names":[],"mappings":"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"}
|