@wallarm-org/design-system 1.31.0 → 1.33.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.
- package/dist/components/CodeEditor/CodeEditorRoot.d.ts +1 -1
- package/dist/components/CodeEditor/engine/SearchPanel.js +17 -3
- package/dist/components/CodeEditor/engine/completion.d.ts +3 -3
- package/dist/components/CodeEditor/engine/completion.js +142 -2
- package/dist/components/CodeEditor/engine/index.js +21 -4
- package/dist/components/Stepper/Stepper.d.ts +22 -0
- package/dist/components/Stepper/Stepper.figma.d.ts +1 -0
- package/dist/components/Stepper/Stepper.figma.js +59 -0
- package/dist/components/Stepper/Stepper.js +34 -0
- package/dist/components/Stepper/StepperContent.d.ts +16 -0
- package/dist/components/Stepper/StepperContent.js +28 -0
- package/dist/components/Stepper/StepperContext.d.ts +58 -0
- package/dist/components/Stepper/StepperContext.js +37 -0
- package/dist/components/Stepper/StepperDescription.d.ts +8 -0
- package/dist/components/Stepper/StepperDescription.js +30 -0
- package/dist/components/Stepper/StepperIndicator.d.ts +9 -0
- package/dist/components/Stepper/StepperIndicator.js +34 -0
- package/dist/components/Stepper/StepperItem.d.ts +19 -0
- package/dist/components/Stepper/StepperItem.js +48 -0
- package/dist/components/Stepper/StepperList.d.ts +12 -0
- package/dist/components/Stepper/StepperList.js +28 -0
- package/dist/components/Stepper/StepperNextTrigger.d.ts +14 -0
- package/dist/components/Stepper/StepperNextTrigger.js +28 -0
- package/dist/components/Stepper/StepperPrevTrigger.d.ts +13 -0
- package/dist/components/Stepper/StepperPrevTrigger.js +31 -0
- package/dist/components/Stepper/StepperRootProvider.d.ts +18 -0
- package/dist/components/Stepper/StepperRootProvider.js +25 -0
- package/dist/components/Stepper/StepperSeparator.d.ts +7 -0
- package/dist/components/Stepper/StepperSeparator.js +28 -0
- package/dist/components/Stepper/StepperTitle.d.ts +8 -0
- package/dist/components/Stepper/StepperTitle.js +32 -0
- package/dist/components/Stepper/StepperTrigger.d.ts +16 -0
- package/dist/components/Stepper/StepperTrigger.js +32 -0
- package/dist/components/Stepper/classes.d.ts +14 -0
- package/dist/components/Stepper/classes.js +37 -0
- package/dist/components/Stepper/constants.d.ts +22 -0
- package/dist/components/Stepper/constants.js +23 -0
- package/dist/components/Stepper/index.d.ts +15 -0
- package/dist/components/Stepper/index.js +14 -0
- package/dist/components/Stepper/takeAsChildDisabled.d.ts +11 -0
- package/dist/components/Stepper/takeAsChildDisabled.js +17 -0
- package/dist/components/Stepper/types.d.ts +11 -0
- package/dist/components/Stepper/types.js +0 -0
- package/dist/components/Stepper/useStepper.d.ts +38 -0
- package/dist/components/Stepper/useStepper.js +58 -0
- package/dist/components/Table/TableBody/TableBodyVirtualizedCore.js +1 -1
- package/dist/components/Table/TableBody/TableBodyVirtualizedWindow.js +30 -8
- package/dist/components/Table/TableInner/TableInnerWindow.js +7 -2
- package/dist/components/Table/hooks/index.d.ts +1 -0
- package/dist/components/Table/hooks/index.js +1 -0
- package/dist/components/Table/hooks/infiniteScroll/useInfiniteScroll.d.ts +4 -2
- package/dist/components/Table/hooks/infiniteScroll/useInfiniteScroll.js +6 -2
- package/dist/components/Table/hooks/infiniteScroll/useInitialAnchor.d.ts +7 -1
- package/dist/components/Table/hooks/infiniteScroll/useInitialAnchor.js +4 -3
- package/dist/components/Table/hooks/infiniteScroll/usePrependScrollAnchor.d.ts +4 -1
- package/dist/components/Table/hooks/infiniteScroll/usePrependScrollAnchor.js +13 -11
- package/dist/components/Table/hooks/infiniteScroll/useScrollEdge.d.ts +4 -1
- package/dist/components/Table/hooks/infiniteScroll/useScrollEdge.js +7 -18
- package/dist/components/Table/hooks/useWindowScrollRoot.d.ts +26 -0
- package/dist/components/Table/hooks/useWindowScrollRoot.js +62 -0
- package/dist/components/Table/lib/index.d.ts +1 -0
- package/dist/components/Table/lib/index.js +1 -0
- package/dist/components/Table/lib/scrollRoot.d.ts +24 -0
- package/dist/components/Table/lib/scrollRoot.js +22 -0
- package/dist/components/Table/types.d.ts +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/metadata/components.json +4104 -433
- package/package.json +1 -1
|
@@ -23,7 +23,7 @@ export interface CodeEditorRootProps extends CodeEditorRootNativeProps, Testable
|
|
|
23
23
|
* document would be seeded with the previous document's text.
|
|
24
24
|
*/
|
|
25
25
|
documentId?: string;
|
|
26
|
-
/**
|
|
26
|
+
/** Non-editable and unfocusable content; text remains selectable, searchable and copyable */
|
|
27
27
|
readOnly?: boolean;
|
|
28
28
|
/** Offsets gutter numbers; `lines`, `folds`, `diagnostics` use absolute numbers */
|
|
29
29
|
startingLineNumber?: number;
|
|
@@ -41,9 +41,20 @@ const SearchPanel = ({ view, query, matchCount, readOnly, testId })=>{
|
|
|
41
41
|
]
|
|
42
42
|
});
|
|
43
43
|
};
|
|
44
|
+
const blurReadOnlyContent = ()=>{
|
|
45
|
+
if (view.state.readOnly && view.hasFocus) view.contentDOM.blur();
|
|
46
|
+
};
|
|
47
|
+
const closeSearch = ()=>{
|
|
48
|
+
closeSearchPanel(view);
|
|
49
|
+
blurReadOnlyContent();
|
|
50
|
+
};
|
|
44
51
|
const handleKeyDown = (event, onEnter)=>{
|
|
45
52
|
if (event.nativeEvent.isComposing || 229 === event.keyCode) return;
|
|
46
|
-
if (runScopeHandlers(view, event.nativeEvent, 'search-panel'))
|
|
53
|
+
if (runScopeHandlers(view, event.nativeEvent, 'search-panel')) {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
blurReadOnlyContent();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
47
58
|
if ('Enter' === event.key) {
|
|
48
59
|
event.preventDefault();
|
|
49
60
|
onEnter(event.shiftKey);
|
|
@@ -53,7 +64,10 @@ const SearchPanel = ({ view, query, matchCount, readOnly, testId })=>{
|
|
|
53
64
|
const handleReplaceKeyDown = (event)=>handleKeyDown(event, ()=>replaceNext(view));
|
|
54
65
|
const handlePanelKeyDown = (event)=>{
|
|
55
66
|
if (event.target instanceof HTMLInputElement) return;
|
|
56
|
-
if (runScopeHandlers(view, event.nativeEvent, 'search-panel'))
|
|
67
|
+
if (runScopeHandlers(view, event.nativeEvent, 'search-panel')) {
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
blurReadOnlyContent();
|
|
70
|
+
}
|
|
57
71
|
};
|
|
58
72
|
const canSearch = query.valid;
|
|
59
73
|
return /*#__PURE__*/ jsxs("div", {
|
|
@@ -154,7 +168,7 @@ const SearchPanel = ({ view, query, matchCount, readOnly, testId })=>{
|
|
|
154
168
|
className: "ml-auto",
|
|
155
169
|
"aria-label": "Close search",
|
|
156
170
|
"data-testid": slot('search-close'),
|
|
157
|
-
onClick:
|
|
171
|
+
onClick: closeSearch,
|
|
158
172
|
children: /*#__PURE__*/ jsx(X, {})
|
|
159
173
|
})
|
|
160
174
|
]
|
|
@@ -4,9 +4,9 @@ import type { CodeEditorCompletionContext, CodeEditorCompletionSource, CodeEdito
|
|
|
4
4
|
/** Public, engine-free view of a CodeMirror completion request (spec §4). */
|
|
5
5
|
export declare const buildCompletionContext: (ctx: CompletionContext, language: CodeEditorLanguage, startingLineNumber: number) => CodeEditorCompletionContext;
|
|
6
6
|
/**
|
|
7
|
-
* Autocomplete
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Autocomplete: HTTP and JSON Schema sources, consumer sources, then language keywords and
|
|
8
|
+
* document words, all through `override` (language-data sources are off).
|
|
9
|
+
* `completionKeymap` comes with `defaultKeymap: true` at `Prec.highest`, so Enter,
|
|
10
10
|
* arrows and Escape reach the open list before `indentWithTab` / fullscreen Escape.
|
|
11
11
|
*/
|
|
12
12
|
export declare const completionExtension: (config: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { autocompletion } from "@codemirror/autocomplete";
|
|
1
|
+
import { autocompletion, completeAnyWord, completeFromList } from "@codemirror/autocomplete";
|
|
2
2
|
import { EditorView } from "@codemirror/view";
|
|
3
3
|
import { cn } from "../../../utils/cn.js";
|
|
4
4
|
import { dropdownMenuItemVariants } from "../../DropdownMenu/classes.js";
|
|
@@ -106,13 +106,153 @@ const adaptSource = (source, language, startingLineNumber)=>(ctx)=>{
|
|
|
106
106
|
}
|
|
107
107
|
};
|
|
108
108
|
const reopensAfter = (completion)=>'string' == typeof completion.apply && completion.apply.endsWith(': ');
|
|
109
|
+
const LANGUAGE_KEYWORDS = {
|
|
110
|
+
json: [
|
|
111
|
+
'true',
|
|
112
|
+
'false',
|
|
113
|
+
'null'
|
|
114
|
+
],
|
|
115
|
+
yaml: [
|
|
116
|
+
'true',
|
|
117
|
+
'false',
|
|
118
|
+
'null'
|
|
119
|
+
],
|
|
120
|
+
bash: [
|
|
121
|
+
'echo',
|
|
122
|
+
'export',
|
|
123
|
+
'if',
|
|
124
|
+
'then',
|
|
125
|
+
'else',
|
|
126
|
+
'fi',
|
|
127
|
+
'for',
|
|
128
|
+
'in',
|
|
129
|
+
'do',
|
|
130
|
+
'done',
|
|
131
|
+
'function'
|
|
132
|
+
],
|
|
133
|
+
javascript: [
|
|
134
|
+
'const',
|
|
135
|
+
'let',
|
|
136
|
+
'var',
|
|
137
|
+
'function',
|
|
138
|
+
'return',
|
|
139
|
+
'if',
|
|
140
|
+
'else',
|
|
141
|
+
'for',
|
|
142
|
+
'while',
|
|
143
|
+
'class',
|
|
144
|
+
'import',
|
|
145
|
+
'export',
|
|
146
|
+
'from',
|
|
147
|
+
'async',
|
|
148
|
+
'await',
|
|
149
|
+
'true',
|
|
150
|
+
'false',
|
|
151
|
+
'null',
|
|
152
|
+
'undefined'
|
|
153
|
+
],
|
|
154
|
+
typescript: [
|
|
155
|
+
'const',
|
|
156
|
+
'let',
|
|
157
|
+
'function',
|
|
158
|
+
'return',
|
|
159
|
+
'if',
|
|
160
|
+
'else',
|
|
161
|
+
'class',
|
|
162
|
+
'import',
|
|
163
|
+
'export',
|
|
164
|
+
'from',
|
|
165
|
+
'async',
|
|
166
|
+
'await',
|
|
167
|
+
'interface',
|
|
168
|
+
'type',
|
|
169
|
+
'enum',
|
|
170
|
+
'extends',
|
|
171
|
+
'implements',
|
|
172
|
+
'public',
|
|
173
|
+
'private',
|
|
174
|
+
'readonly',
|
|
175
|
+
'true',
|
|
176
|
+
'false',
|
|
177
|
+
'null',
|
|
178
|
+
'undefined'
|
|
179
|
+
],
|
|
180
|
+
python: [
|
|
181
|
+
'def',
|
|
182
|
+
'class',
|
|
183
|
+
'return',
|
|
184
|
+
'if',
|
|
185
|
+
'elif',
|
|
186
|
+
'else',
|
|
187
|
+
'for',
|
|
188
|
+
'while',
|
|
189
|
+
'in',
|
|
190
|
+
'import',
|
|
191
|
+
'from',
|
|
192
|
+
'as',
|
|
193
|
+
'async',
|
|
194
|
+
'await',
|
|
195
|
+
'try',
|
|
196
|
+
'except',
|
|
197
|
+
'with',
|
|
198
|
+
'True',
|
|
199
|
+
'False',
|
|
200
|
+
'None'
|
|
201
|
+
],
|
|
202
|
+
lua: [
|
|
203
|
+
'function',
|
|
204
|
+
'local',
|
|
205
|
+
'return',
|
|
206
|
+
'if',
|
|
207
|
+
'then',
|
|
208
|
+
'elseif',
|
|
209
|
+
'else',
|
|
210
|
+
'end',
|
|
211
|
+
'for',
|
|
212
|
+
'while',
|
|
213
|
+
'do',
|
|
214
|
+
'repeat',
|
|
215
|
+
'until',
|
|
216
|
+
'true',
|
|
217
|
+
'false',
|
|
218
|
+
'nil'
|
|
219
|
+
]
|
|
220
|
+
};
|
|
221
|
+
const isInsideQuotedString = (text)=>{
|
|
222
|
+
let quoted = false;
|
|
223
|
+
for(let i = 0; i < text.length; i++)if ('\\' === text[i]) i++;
|
|
224
|
+
else if ('"' === text[i]) quoted = !quoted;
|
|
225
|
+
return quoted;
|
|
226
|
+
};
|
|
227
|
+
const builtInSources = (language)=>{
|
|
228
|
+
const keywords = LANGUAGE_KEYWORDS[language];
|
|
229
|
+
if (!keywords) return [
|
|
230
|
+
completeAnyWord
|
|
231
|
+
];
|
|
232
|
+
const completeKeywords = completeFromList(keywords.map((label)=>({
|
|
233
|
+
label,
|
|
234
|
+
type: 'keyword'
|
|
235
|
+
})));
|
|
236
|
+
if ('json' === language) return [
|
|
237
|
+
(ctx)=>{
|
|
238
|
+
const line = ctx.state.doc.lineAt(ctx.pos);
|
|
239
|
+
const before = line.text.slice(0, ctx.pos - line.from);
|
|
240
|
+
if (isInsideQuotedString(before)) return completeAnyWord(ctx);
|
|
241
|
+
return /(?:^|[:,\[])[\s\w]*$/.test(before) ? completeKeywords(ctx) : null;
|
|
242
|
+
}
|
|
243
|
+
];
|
|
244
|
+
return [
|
|
245
|
+
completeKeywords,
|
|
246
|
+
completeAnyWord
|
|
247
|
+
];
|
|
248
|
+
};
|
|
109
249
|
const completionExtension = (config)=>{
|
|
110
250
|
const { language, schema, sources, startingLineNumber } = config;
|
|
111
251
|
const override = [];
|
|
112
252
|
if ('http' === language) override.push(adaptSource(httpCompletions, language, startingLineNumber));
|
|
113
253
|
if (void 0 !== schema && isJsonLike(language)) override.push(schemaCompletionSource(()=>schema, (state)=>jsonRegion(state, language)));
|
|
114
254
|
for (const source of sources)override.push(adaptSource(source, language, startingLineNumber));
|
|
115
|
-
|
|
255
|
+
override.push(...builtInSources(language));
|
|
116
256
|
return [
|
|
117
257
|
autocompletion({
|
|
118
258
|
override,
|
|
@@ -79,7 +79,8 @@ const SLOT_DEPS = {
|
|
|
79
79
|
],
|
|
80
80
|
contentAttributes: [
|
|
81
81
|
'contentAttributes',
|
|
82
|
-
'testId'
|
|
82
|
+
'testId',
|
|
83
|
+
'readOnly'
|
|
83
84
|
],
|
|
84
85
|
cspNonce: [
|
|
85
86
|
'cspNonce'
|
|
@@ -184,6 +185,7 @@ const featureExtensions = (options, callbacks)=>({
|
|
|
184
185
|
});
|
|
185
186
|
const contentAttributesFor = (options)=>{
|
|
186
187
|
const attrs = sanitizeContentAttributes(options.contentAttributes);
|
|
188
|
+
if (options.readOnly) delete attrs.tabindex;
|
|
187
189
|
if (options.testId) attrs['data-testid'] = `${options.testId}--editor`;
|
|
188
190
|
return attrs;
|
|
189
191
|
};
|
|
@@ -225,7 +227,10 @@ const gutterAria = [
|
|
|
225
227
|
];
|
|
226
228
|
const slotExtensions = (options, callbacks)=>({
|
|
227
229
|
language: ()=>languageExtension(options.language),
|
|
228
|
-
readOnly: ()=>
|
|
230
|
+
readOnly: ()=>[
|
|
231
|
+
EditorState.readOnly.of(options.readOnly),
|
|
232
|
+
EditorView.editable.of(!options.readOnly)
|
|
233
|
+
],
|
|
229
234
|
wrap: ()=>options.wrapLines ? EditorView.lineWrapping : [],
|
|
230
235
|
maxHeight: ()=>maxHeightTheme(options.maxHeight),
|
|
231
236
|
contentAttributes: ()=>EditorView.contentAttributes.of(contentAttributesFor(options)),
|
|
@@ -298,6 +303,10 @@ const createEditor = (parent, initialOptions, callbacks)=>{
|
|
|
298
303
|
state: createState(initialOptions.value, initialOptions),
|
|
299
304
|
parent
|
|
300
305
|
});
|
|
306
|
+
const preventReadOnlyMouseFocus = (event)=>{
|
|
307
|
+
if (view.state.readOnly && event.target instanceof Node && view.contentDOM.contains(event.target)) event.stopPropagation();
|
|
308
|
+
};
|
|
309
|
+
view.dom.addEventListener('mousedown', preventReadOnlyMouseFocus, true);
|
|
301
310
|
const ensureLazyLanguage = (lang)=>{
|
|
302
311
|
if (!isLazyLanguage(lang)) return;
|
|
303
312
|
loadLanguageExtension(lang).then((extension)=>{
|
|
@@ -346,13 +355,20 @@ const createEditor = (parent, initialOptions, callbacks)=>{
|
|
|
346
355
|
const update = (next)=>{
|
|
347
356
|
const prev = options;
|
|
348
357
|
options = next;
|
|
349
|
-
if (next.documentId !== prev.documentId)
|
|
358
|
+
if (next.documentId !== prev.documentId) {
|
|
359
|
+
swapDocument(prev, next);
|
|
360
|
+
if (next.readOnly && view.hasFocus) view.contentDOM.blur();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
350
363
|
reconfigure(prev, next);
|
|
364
|
+
if (next.readOnly && view.hasFocus) view.contentDOM.blur();
|
|
351
365
|
if (next.language !== prev.language) ensureLazyLanguage(next.language);
|
|
352
366
|
syncValue(next.value);
|
|
353
367
|
};
|
|
354
368
|
const api = {
|
|
355
|
-
focus: ()=>
|
|
369
|
+
focus: ()=>{
|
|
370
|
+
if (!view.state.readOnly) view.focus();
|
|
371
|
+
},
|
|
356
372
|
getValue: ()=>view.state.doc.toString(),
|
|
357
373
|
insertText: (text)=>{
|
|
358
374
|
if (view.state.readOnly) return;
|
|
@@ -380,6 +396,7 @@ const createEditor = (parent, initialOptions, callbacks)=>{
|
|
|
380
396
|
destroy: ()=>{
|
|
381
397
|
destroyed = true;
|
|
382
398
|
cache.clear();
|
|
399
|
+
view.dom.removeEventListener('mousedown', preventReadOnlyMouseFocus, true);
|
|
383
400
|
view.destroy();
|
|
384
401
|
}
|
|
385
402
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { FC, ReactNode, Ref } from 'react';
|
|
2
|
+
import { Steps as ArkSteps } from '@ark-ui/react/steps';
|
|
3
|
+
import { type TestableProps } from '../../utils/testId';
|
|
4
|
+
import type { StepperStatusLabels } from './types';
|
|
5
|
+
import { type StepperGuardProps, type StepperOmittedArkProps } from './useStepper';
|
|
6
|
+
export interface StepperProps extends Omit<ArkSteps.RootProps, StepperOmittedArkProps | keyof StepperGuardProps | 'asChild'>, StepperGuardProps, TestableProps {
|
|
7
|
+
/** `StepperList`, then optional `StepperContent`s and `StepperPrevTrigger` / `StepperNextTrigger`. */
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
/** Screen-reader-only suffixes for completed and danger steps. */
|
|
10
|
+
statusLabels?: StepperStatusLabels;
|
|
11
|
+
ref?: Ref<HTMLDivElement>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A horizontal row of numbered steps for a multi-step flow, such as a create drawer. Every step is
|
|
15
|
+
* a button, so people can move back and forward freely; the page owns each step's status
|
|
16
|
+
* (completed, danger, upcoming) and the current step is always shown as active.
|
|
17
|
+
*
|
|
18
|
+
* Compound, like Ark UI Steps: `StepperList` › `StepperItem index` › `StepperTrigger` (with
|
|
19
|
+
* `StepperIndicator`, `StepperTitle`, `StepperDescription`) and `StepperSeparator`, then optional
|
|
20
|
+
* `StepperContent index`, `StepperPrevTrigger` and `StepperNextTrigger`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const Stepper: FC<StepperProps>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import code_connect from "@figma/code-connect";
|
|
3
|
+
import { Stepper } from "./Stepper.js";
|
|
4
|
+
import { StepperDescription } from "./StepperDescription.js";
|
|
5
|
+
import { StepperIndicator } from "./StepperIndicator.js";
|
|
6
|
+
import { StepperItem } from "./StepperItem.js";
|
|
7
|
+
import { StepperList } from "./StepperList.js";
|
|
8
|
+
import { StepperSeparator } from "./StepperSeparator.js";
|
|
9
|
+
import { StepperTitle } from "./StepperTitle.js";
|
|
10
|
+
import { StepperTrigger } from "./StepperTrigger.js";
|
|
11
|
+
const STEPPER_URL = 'https://www.figma.com/design/VKb5gW46uSGw0rqrhZsbXT/WADS-Components?node-id=12463-208988';
|
|
12
|
+
const STEPPER_ITEM_URL = 'https://www.figma.com/design/VKb5gW46uSGw0rqrhZsbXT/WADS-Components?node-id=12463-208896';
|
|
13
|
+
code_connect.connect(Stepper, STEPPER_URL, {
|
|
14
|
+
props: {
|
|
15
|
+
children: code_connect.children('stepper-item')
|
|
16
|
+
},
|
|
17
|
+
example: ({ children })=>/*#__PURE__*/ jsx(Stepper, {
|
|
18
|
+
count: 4,
|
|
19
|
+
step: 0,
|
|
20
|
+
onStepChange: ()=>void 0,
|
|
21
|
+
children: /*#__PURE__*/ jsx(StepperList, {
|
|
22
|
+
"aria-label": "Steps",
|
|
23
|
+
children: children
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
code_connect.connect(StepperItem, STEPPER_ITEM_URL, {
|
|
28
|
+
props: {
|
|
29
|
+
status: code_connect["enum"]('Type', {
|
|
30
|
+
Completed: 'completed',
|
|
31
|
+
Danger: 'danger',
|
|
32
|
+
Upcoming: 'upcoming',
|
|
33
|
+
Active: void 0
|
|
34
|
+
}),
|
|
35
|
+
title: code_connect.string('step'),
|
|
36
|
+
description: code_connect.boolean("description", {
|
|
37
|
+
true: code_connect.string("descriptionText"),
|
|
38
|
+
false: void 0
|
|
39
|
+
})
|
|
40
|
+
},
|
|
41
|
+
example: ({ status, title, description })=>/*#__PURE__*/ jsxs(StepperItem, {
|
|
42
|
+
index: 0,
|
|
43
|
+
status: status,
|
|
44
|
+
children: [
|
|
45
|
+
/*#__PURE__*/ jsxs(StepperTrigger, {
|
|
46
|
+
children: [
|
|
47
|
+
/*#__PURE__*/ jsx(StepperIndicator, {}),
|
|
48
|
+
/*#__PURE__*/ jsx(StepperTitle, {
|
|
49
|
+
children: title
|
|
50
|
+
}),
|
|
51
|
+
description && /*#__PURE__*/ jsx(StepperDescription, {
|
|
52
|
+
children: description
|
|
53
|
+
})
|
|
54
|
+
]
|
|
55
|
+
}),
|
|
56
|
+
/*#__PURE__*/ jsx(StepperSeparator, {})
|
|
57
|
+
]
|
|
58
|
+
})
|
|
59
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Steps } from "@ark-ui/react/steps";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { TestIdProvider } from "../../utils/testId.js";
|
|
5
|
+
import { stepperVariants } from "./classes.js";
|
|
6
|
+
import { StepperRootContext } from "./StepperContext.js";
|
|
7
|
+
import { useStepperGuards } from "./useStepper.js";
|
|
8
|
+
const Stepper = ({ children, count, step, defaultStep, onStepChange, statusLabels, className, ref, 'data-testid': testId, ...rest })=>{
|
|
9
|
+
const guarded = useStepperGuards({
|
|
10
|
+
count,
|
|
11
|
+
step,
|
|
12
|
+
defaultStep,
|
|
13
|
+
onStepChange
|
|
14
|
+
});
|
|
15
|
+
return /*#__PURE__*/ jsx(Steps.Root, {
|
|
16
|
+
...rest,
|
|
17
|
+
...guarded,
|
|
18
|
+
ref: ref,
|
|
19
|
+
"data-slot": "stepper",
|
|
20
|
+
"data-testid": testId,
|
|
21
|
+
className: cn(stepperVariants(), className),
|
|
22
|
+
children: /*#__PURE__*/ jsx(TestIdProvider, {
|
|
23
|
+
value: testId,
|
|
24
|
+
children: /*#__PURE__*/ jsx(StepperRootContext.Provider, {
|
|
25
|
+
value: {
|
|
26
|
+
statusLabels
|
|
27
|
+
},
|
|
28
|
+
children: children
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
Stepper.displayName = 'Stepper';
|
|
34
|
+
export { Stepper };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
|
|
2
|
+
import { type TestableProps } from '../../utils/testId';
|
|
3
|
+
export interface StepperContentProps extends HTMLAttributes<HTMLDivElement>, TestableProps {
|
|
4
|
+
/** 0-based step this body belongs to. */
|
|
5
|
+
index: number;
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
ref?: Ref<HTMLDivElement>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The body of one step, shown only while that step is current. Every body stays mounted (hidden),
|
|
11
|
+
* so form state survives moving between steps. It is a `group` named by its `StepperTrigger`
|
|
12
|
+
* (Ark's `aria-labelledby`), so render the matching trigger in the same `Stepper`. Set trigger
|
|
13
|
+
* ids with the root `ids.triggerId` prop, not an `id` on `StepperTrigger`: the body only knows the
|
|
14
|
+
* root's ids.
|
|
15
|
+
*/
|
|
16
|
+
export declare const StepperContent: FC<StepperContentProps>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Steps, useStepsContext } from "@ark-ui/react/steps";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { useTestId } from "../../utils/testId.js";
|
|
5
|
+
import { stepperContentVariants } from "./classes.js";
|
|
6
|
+
import { ARK_CONTENT_ARIA_RESET } from "./constants.js";
|
|
7
|
+
import { clampStep, useStepperRootContext } from "./StepperContext.js";
|
|
8
|
+
const StepperContent = ({ index, children, className, ref, 'data-testid': testIdProp, ...rest })=>{
|
|
9
|
+
useStepperRootContext('StepperContent');
|
|
10
|
+
const { value, count } = useStepsContext();
|
|
11
|
+
const current = index === clampStep(value, count);
|
|
12
|
+
const testId = useTestId(`content-${index}`, testIdProp);
|
|
13
|
+
return /*#__PURE__*/ jsx(Steps.Content, {
|
|
14
|
+
index: index,
|
|
15
|
+
...ARK_CONTENT_ARIA_RESET,
|
|
16
|
+
role: "group",
|
|
17
|
+
...rest,
|
|
18
|
+
ref: ref,
|
|
19
|
+
hidden: !current,
|
|
20
|
+
"data-state": current ? 'open' : 'closed',
|
|
21
|
+
"data-slot": "stepper-content",
|
|
22
|
+
"data-testid": testId,
|
|
23
|
+
className: cn(stepperContentVariants(), className),
|
|
24
|
+
children: children
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
StepperContent.displayName = 'StepperContent';
|
|
28
|
+
export { StepperContent };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { StepperStatusLabels, StepperVisualStatus } from './types';
|
|
2
|
+
interface StepperRootContextValue {
|
|
3
|
+
statusLabels?: StepperStatusLabels;
|
|
4
|
+
}
|
|
5
|
+
export declare const StepperRootContext: import("react").Context<StepperRootContextValue | undefined>;
|
|
6
|
+
/**
|
|
7
|
+
* Reads the enclosing `Stepper` / `StepperRootProvider`. Called first by every root-level part, so
|
|
8
|
+
* misuse throws a `[Stepper]` error instead of Ark's internal `useStepsContext` one.
|
|
9
|
+
*/
|
|
10
|
+
export declare const useStepperRootContext: (part: string) => StepperRootContextValue;
|
|
11
|
+
/** `true` inside a `StepperList`, so a `StepperItem` can tell it is rendered outside one. */
|
|
12
|
+
export declare const StepperListContext: import("react").Context<boolean>;
|
|
13
|
+
export interface StepperItemContextValue {
|
|
14
|
+
/** 0-based position, from the item's `index` prop. */
|
|
15
|
+
index: number;
|
|
16
|
+
/** This item is the current step. */
|
|
17
|
+
current: boolean;
|
|
18
|
+
/** This item is the last step: it renders no separator. */
|
|
19
|
+
last: boolean;
|
|
20
|
+
/** Rendered state: `'active'` while current, else the item's `status`. */
|
|
21
|
+
status: StepperVisualStatus;
|
|
22
|
+
/** Screen-reader-only suffix for completed and danger steps, already resolved. */
|
|
23
|
+
statusLabel?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare const StepperItemContext: import("react").Context<StepperItemContextValue | undefined>;
|
|
26
|
+
/** Reads the enclosing `StepperItem`: `{ index, current, last, status }`. */
|
|
27
|
+
export declare const useStepperItemContext: () => StepperItemContextValue;
|
|
28
|
+
/**
|
|
29
|
+
* The current step, clamped to `[0, count - 1]`. Zag accepts `count` as a step (its "completed"
|
|
30
|
+
* state, where no step is current) and checks the range only on mount, so a step can fall out of
|
|
31
|
+
* range; the Stepper always shows one current step.
|
|
32
|
+
*/
|
|
33
|
+
export declare const clampStep: (value: number, count: number) => number;
|
|
34
|
+
export interface UseStepperContextReturn {
|
|
35
|
+
/** Current step, 0-based, always in `[0, count - 1]`. */
|
|
36
|
+
value: number;
|
|
37
|
+
/** Number of steps. */
|
|
38
|
+
count: number;
|
|
39
|
+
/** There is a later step. `false` on the last step. */
|
|
40
|
+
hasNextStep: boolean;
|
|
41
|
+
/** There is an earlier step. `false` on the first step. */
|
|
42
|
+
hasPrevStep: boolean;
|
|
43
|
+
/** Moves to the next step; does nothing on the last step. */
|
|
44
|
+
goToNextStep: () => void;
|
|
45
|
+
/** Moves to the previous step; does nothing on the first step. */
|
|
46
|
+
goToPrevStep: () => void;
|
|
47
|
+
/** Moves to the first step. */
|
|
48
|
+
resetStep: () => void;
|
|
49
|
+
/** Moves to `step`, clamped to `[0, count - 1]`. */
|
|
50
|
+
setStep: (step: number) => void;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Reads the enclosing `Stepper`. Wraps Ark's `useStepsContext`, with one difference: it never
|
|
54
|
+
* moves past the last step, so there is always a current step (Ark's "completed" state is not
|
|
55
|
+
* part of the Stepper).
|
|
56
|
+
*/
|
|
57
|
+
export declare const useStepperContext: () => UseStepperContextReturn;
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import { useStepsContext } from "@ark-ui/react/steps";
|
|
3
|
+
const StepperRootContext = /*#__PURE__*/ createContext(void 0);
|
|
4
|
+
const useStepperRootContext = (part)=>{
|
|
5
|
+
const context = useContext(StepperRootContext);
|
|
6
|
+
if (!context) throw new Error(`[Stepper] ${part} must be used inside a Stepper or StepperRootProvider.`);
|
|
7
|
+
return context;
|
|
8
|
+
};
|
|
9
|
+
const StepperListContext = /*#__PURE__*/ createContext(false);
|
|
10
|
+
const StepperItemContext = /*#__PURE__*/ createContext(void 0);
|
|
11
|
+
const useStepperItemContext = ()=>{
|
|
12
|
+
const context = useContext(StepperItemContext);
|
|
13
|
+
if (!context) throw new Error('[Stepper] useStepperItemContext must be used inside a StepperItem.');
|
|
14
|
+
return context;
|
|
15
|
+
};
|
|
16
|
+
const clampStep = (value, count)=>Math.min(Math.max(value, 0), Math.max(count - 1, 0));
|
|
17
|
+
const useStepperContext = ()=>{
|
|
18
|
+
useStepperRootContext('useStepperContext');
|
|
19
|
+
const api = useStepsContext();
|
|
20
|
+
const value = clampStep(api.value, api.count);
|
|
21
|
+
const hasNextStep = value < api.count - 1;
|
|
22
|
+
return {
|
|
23
|
+
value,
|
|
24
|
+
count: api.count,
|
|
25
|
+
hasNextStep,
|
|
26
|
+
hasPrevStep: value > 0,
|
|
27
|
+
goToNextStep: ()=>{
|
|
28
|
+
if (hasNextStep) api.setStep(value + 1);
|
|
29
|
+
},
|
|
30
|
+
goToPrevStep: ()=>{
|
|
31
|
+
if (value > 0) api.setStep(value - 1);
|
|
32
|
+
},
|
|
33
|
+
resetStep: api.resetStep,
|
|
34
|
+
setStep: (step)=>api.setStep(clampStep(step, api.count))
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export { StepperItemContext, StepperListContext, StepperRootContext, clampStep, useStepperContext, useStepperItemContext, useStepperRootContext };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
|
|
2
|
+
import { type TestableProps } from '../../utils/testId';
|
|
3
|
+
export interface StepperDescriptionProps extends HTMLAttributes<HTMLSpanElement>, TestableProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
ref?: Ref<HTMLSpanElement>;
|
|
6
|
+
}
|
|
7
|
+
/** An optional second line under the title, e.g. 'Optional' or 'Request · Lua · HMAC auth'. One line, ellipsis at 320px, with the full text in a tooltip when it overflows. */
|
|
8
|
+
export declare const StepperDescription: FC<StepperDescriptionProps>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
import { useTestId } from "../../utils/testId.js";
|
|
4
|
+
import { OverflowTooltip, OverflowTooltipContent, OverflowTooltipTrigger } from "../OverflowTooltip/index.js";
|
|
5
|
+
import { stepperDescriptionVariants } from "./classes.js";
|
|
6
|
+
import { useStepperItemContext } from "./StepperContext.js";
|
|
7
|
+
const StepperDescription = ({ children, className, ref, 'data-testid': testIdProp, ...rest })=>{
|
|
8
|
+
const { status } = useStepperItemContext();
|
|
9
|
+
const testId = useTestId("description", testIdProp);
|
|
10
|
+
return /*#__PURE__*/ jsxs(OverflowTooltip, {
|
|
11
|
+
children: [
|
|
12
|
+
/*#__PURE__*/ jsx(OverflowTooltipTrigger, {
|
|
13
|
+
ref: ref,
|
|
14
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
15
|
+
...rest,
|
|
16
|
+
"data-slot": "stepper-description",
|
|
17
|
+
"data-status": status,
|
|
18
|
+
"data-testid": testId,
|
|
19
|
+
className: cn(stepperDescriptionVariants(), className),
|
|
20
|
+
children: children
|
|
21
|
+
})
|
|
22
|
+
}),
|
|
23
|
+
/*#__PURE__*/ jsx(OverflowTooltipContent, {
|
|
24
|
+
children: children
|
|
25
|
+
})
|
|
26
|
+
]
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
StepperDescription.displayName = "StepperDescription";
|
|
30
|
+
export { StepperDescription };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
|
|
2
|
+
import { type TestableProps } from '../../utils/testId';
|
|
3
|
+
export interface StepperIndicatorProps extends HTMLAttributes<HTMLSpanElement>, TestableProps {
|
|
4
|
+
/** Replaces the default content: the step number, `!` for danger, a check for completed. */
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
ref?: Ref<HTMLSpanElement>;
|
|
7
|
+
}
|
|
8
|
+
/** The step badge. Decorative: Ark marks it `aria-hidden`, the title names the step. */
|
|
9
|
+
export declare const StepperIndicator: FC<StepperIndicatorProps>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Steps } from "@ark-ui/react/steps";
|
|
3
|
+
import { Check } from "../../icons/index.js";
|
|
4
|
+
import { cn } from "../../utils/cn.js";
|
|
5
|
+
import { useTestId } from "../../utils/testId.js";
|
|
6
|
+
import { stepperIndicatorVariants } from "./classes.js";
|
|
7
|
+
import { useStepperItemContext } from "./StepperContext.js";
|
|
8
|
+
const renderDefault = (status, index)=>{
|
|
9
|
+
if ('completed' === status) return /*#__PURE__*/ jsx(Check, {
|
|
10
|
+
size: "sm"
|
|
11
|
+
});
|
|
12
|
+
if ('danger' === status) return '!';
|
|
13
|
+
return index + 1;
|
|
14
|
+
};
|
|
15
|
+
const StepperIndicator = ({ children, className, ref, 'data-testid': testIdProp, ...rest })=>{
|
|
16
|
+
const { index, status } = useStepperItemContext();
|
|
17
|
+
const testId = useTestId('indicator', testIdProp);
|
|
18
|
+
return /*#__PURE__*/ jsx(Steps.Indicator, {
|
|
19
|
+
asChild: true,
|
|
20
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
21
|
+
...rest,
|
|
22
|
+
ref: ref,
|
|
23
|
+
"data-slot": "stepper-indicator",
|
|
24
|
+
"data-status": status,
|
|
25
|
+
"data-testid": testId,
|
|
26
|
+
className: cn(stepperIndicatorVariants({
|
|
27
|
+
status
|
|
28
|
+
}), className),
|
|
29
|
+
children: children ?? renderDefault(status, index)
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
StepperIndicator.displayName = 'StepperIndicator';
|
|
34
|
+
export { StepperIndicator };
|