@drivenets/design-system 0.13.0 → 0.15.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/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/dist/index.cjs +1155 -381
- package/dist/index.d.cts +371 -21
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +371 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1151 -381
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +16 -13
- package/src/components/ds-button-v3/ds-button-v3.figma.ts +99 -0
- package/src/components/ds-button-v3/ds-button-v3.module.scss +22 -22
- package/src/components/ds-card/figma/ds-card-content.figma.ts +15 -0
- package/src/components/ds-card/figma/ds-card-footer.figma.ts +15 -0
- package/src/components/ds-card/figma/ds-card-header.figma.ts +15 -0
- package/src/components/ds-card/figma/ds-card.figma.ts +72 -0
- package/src/components/ds-date-picker/ds-date-picker.figma.ts +19 -0
- package/src/components/ds-drawer/ds-drawer.module.scss +14 -0
- package/src/components/ds-drawer/ds-drawer.tsx +20 -1
- package/src/components/ds-drawer/ds-drawer.types.ts +7 -0
- package/src/components/ds-file-upload/hooks/use-file-upload.ts +7 -0
- package/src/components/ds-form-control/ds-form-control.figma.ts +76 -0
- package/src/components/ds-icon/figma/ds-icon-material.figma.batch.ts +10 -0
- package/src/components/ds-icon/figma/ds-icon-special.figma.batch.ts +18 -0
- package/src/components/ds-icon/figma/ds-icon.figma.batch.json +2873 -0
- package/src/components/ds-modal/figma/ds-modal-content.figma.ts +18 -0
- package/src/components/ds-modal/figma/ds-modal-footer.figma.ts +19 -0
- package/src/components/ds-modal/figma/ds-modal-header.figma.ts +21 -0
- package/src/components/ds-modal/figma/ds-modal.figma.ts +36 -0
- package/src/components/ds-popover/ds-popover.module.scss +58 -16
- package/src/components/ds-popover/ds-popover.tsx +148 -24
- package/src/components/ds-popover/ds-popover.types.ts +95 -12
- package/src/components/ds-popover/index.ts +1 -1
- package/src/components/ds-progress-task-bar/ds-progress-task-bar.figma.ts +29 -0
- package/src/components/ds-progress-task-bar/ds-progress-task-bar.module.scss +39 -0
- package/src/components/ds-progress-task-bar/ds-progress-task-bar.tsx +122 -0
- package/src/components/ds-progress-task-bar/ds-progress-task-bar.types.ts +65 -0
- package/src/components/ds-progress-task-bar/index.ts +2 -0
- package/src/components/ds-progress-task-bar/utils.ts +51 -0
- package/src/components/ds-select/ds-select.figma.ts +53 -0
- package/src/components/ds-split-button/ds-split-button.figma.ts +95 -0
- package/src/components/ds-status-badge-v2/ds-status-badge-v2.figma.ts +41 -0
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.tsx +8 -3
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.module.scss +31 -0
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.tsx +48 -0
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.types.ts +12 -0
- package/src/components/ds-table/components/ds-table-group-header-cell/index.ts +2 -0
- package/src/components/ds-table/components/ds-table-header/ds-table-header.module.scss +4 -0
- package/src/components/ds-table/components/ds-table-header/ds-table-header.tsx +55 -39
- package/src/components/ds-table/components/ds-table-row/ds-table-row.module.scss +5 -1
- package/src/components/ds-table/components/ds-table-row/ds-table-row.tsx +4 -0
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.module.scss +5 -1
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.tsx +4 -0
- package/src/components/ds-table/components/edit/ds-table-editable-cell/ds-table-editable-cell.module.scss +14 -2
- package/src/components/ds-table/components/edit/ds-table-editable-cell/ds-table-editable-cell.tsx +19 -0
- package/src/components/ds-table/context/ds-table-context.ts +4 -0
- package/src/components/ds-table/ds-table-column.types.ts +24 -0
- package/src/components/ds-table/ds-table.tsx +48 -6
- package/src/components/ds-table/ds-table.types.ts +62 -0
- package/src/components/ds-table/figma/ds-table-expandable.figma.ts +17 -0
- package/src/components/ds-table/figma/ds-table.figma.ts +16 -0
- package/src/components/ds-table/grouping/hooks/use-column-groups.ts +73 -0
- package/src/components/ds-table/grouping/index.ts +5 -0
- package/src/components/ds-table/grouping/types/column-group-meta.augmentation.ts +26 -0
- package/src/components/ds-table/grouping/types/column-group.types.ts +35 -0
- package/src/components/ds-table/grouping/utils/column-group.ts +119 -0
- package/src/components/ds-table/index.ts +4 -0
- package/src/components/ds-table/styles/_variables.scss +1 -0
- package/src/components/ds-table/utils/constants.ts +5 -0
- package/src/components/ds-tabs/figma/ds-tabs-tab-vertical.figma.ts +78 -0
- package/src/components/ds-tabs/figma/ds-tabs-tab.figma.ts +89 -0
- package/src/components/ds-tabs/figma/ds-tabs-vertical.figma.ts +31 -0
- package/src/components/ds-tabs/figma/ds-tabs.figma.ts +29 -0
- package/src/components/ds-tag/ds-tag.module.scss +22 -1
- package/src/components/ds-tag/ds-tag.tsx +16 -3
- package/src/components/ds-tag/ds-tag.types.ts +22 -8
- package/src/components/ds-tag/ds-tag.unit.test.ts +32 -0
- package/src/components/ds-tag-filter/ds-tag-filter.tsx +14 -22
- package/src/components/ds-text-input/ds-text-input.figma.ts +60 -0
- package/src/components/ds-time-picker/ds-time-picker.figma.ts +18 -0
- package/src/index.ts +1 -0
- package/src/styles/_root_new.scss +2 -0
- package/src/styles/_scrollbars.scss +27 -50
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drivenets/design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.cts",
|
|
@@ -36,21 +36,20 @@
|
|
|
36
36
|
"directory": "/packages/design-system"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@ark-ui/react": "^5.
|
|
39
|
+
"@ark-ui/react": "^5.37.2",
|
|
40
40
|
"@dnd-kit/core": "^6.3.1",
|
|
41
41
|
"@dnd-kit/modifiers": "^9.0.0",
|
|
42
42
|
"@dnd-kit/sortable": "^10.0.0",
|
|
43
43
|
"@dnd-kit/utilities": "^3.2.2",
|
|
44
|
-
"@radix-ui/react-collapsible": "^1.1.
|
|
45
|
-
"@radix-ui/react-dialog": "^1.1.
|
|
46
|
-
"@radix-ui/react-dropdown-menu": "^2.1.
|
|
47
|
-
"@radix-ui/react-
|
|
48
|
-
"@radix-ui/react-
|
|
49
|
-
"@radix-ui/react-visually-hidden": "^1.2.4",
|
|
44
|
+
"@radix-ui/react-collapsible": "^1.1.13",
|
|
45
|
+
"@radix-ui/react-dialog": "^1.1.16",
|
|
46
|
+
"@radix-ui/react-dropdown-menu": "^2.1.17",
|
|
47
|
+
"@radix-ui/react-tooltip": "^1.2.9",
|
|
48
|
+
"@radix-ui/react-visually-hidden": "^1.2.5",
|
|
50
49
|
"@tanstack/react-table": "^8.21.3",
|
|
51
|
-
"@tanstack/react-virtual": "^3.
|
|
52
|
-
"@zag-js/react": "^1.
|
|
53
|
-
"@zag-js/steps": "^1.
|
|
50
|
+
"@tanstack/react-virtual": "^3.14.2",
|
|
51
|
+
"@zag-js/react": "^1.41.2",
|
|
52
|
+
"@zag-js/steps": "^1.41.2",
|
|
54
53
|
"classnames": "^2.5.1",
|
|
55
54
|
"csstype": "^3.2.3"
|
|
56
55
|
},
|
|
@@ -64,6 +63,8 @@
|
|
|
64
63
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
65
64
|
"@eslint/compat": "^2.1.0",
|
|
66
65
|
"@faker-js/faker": "^10.3.0",
|
|
66
|
+
"@figma/code-connect": "^1.4.8",
|
|
67
|
+
"@github-ui/storybook-addon-performance-panel": "^1.1.4",
|
|
67
68
|
"@hookform/resolvers": "^5.4.0",
|
|
68
69
|
"@rolldown/plugin-babel": "^0.2.3",
|
|
69
70
|
"@storybook/addon-a11y": "^10.4.1",
|
|
@@ -104,8 +105,8 @@
|
|
|
104
105
|
"vitest": "^4.1.7",
|
|
105
106
|
"vitest-browser-react": "^2.1.0",
|
|
106
107
|
"zod": "^4.4.3",
|
|
107
|
-
"@drivenets/
|
|
108
|
-
"@drivenets/
|
|
108
|
+
"@drivenets/vite-plugin-design-system": "0.0.10",
|
|
109
|
+
"@drivenets/eslint-plugin-internal": "0.0.0"
|
|
109
110
|
},
|
|
110
111
|
"scripts": {
|
|
111
112
|
"start": "storybook dev -p 6006",
|
|
@@ -116,6 +117,8 @@
|
|
|
116
117
|
"lint:build": "publint && attw --pack",
|
|
117
118
|
"typecheck": "pnpm generate-scss-dts && tsgo; EXIT_CODE=$?; rm -rf .scss-dts; exit $EXIT_CODE",
|
|
118
119
|
"generate-scss-dts": "typed-scss-modules ./src -o ./.scss-dts --nameFormat all --exportType default > /dev/null 2>&1",
|
|
120
|
+
"figma:lint": "figma connect parse --exit-on-unreadable-files",
|
|
121
|
+
"figma:publish": "figma connect publish --exit-on-unreadable-files",
|
|
119
122
|
"test": "vitest --project=\"!requires-build\"",
|
|
120
123
|
"test:coverage": "pnpm test --coverage",
|
|
121
124
|
"test:unit": "vitest --project=unit",
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=31065-2352
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-button-v3
|
|
3
|
+
// component=DsButtonV3
|
|
4
|
+
import figma from 'figma';
|
|
5
|
+
|
|
6
|
+
const instance = figma.selectedInstance;
|
|
7
|
+
|
|
8
|
+
const variant = instance.getEnum('Variant', {
|
|
9
|
+
primary: 'primary',
|
|
10
|
+
secondary: 'secondary',
|
|
11
|
+
tertiary: 'tertiary',
|
|
12
|
+
});
|
|
13
|
+
const size = instance.getEnum('Size', {
|
|
14
|
+
tiny: 'tiny',
|
|
15
|
+
small: 'small',
|
|
16
|
+
medium: 'medium',
|
|
17
|
+
large: 'large',
|
|
18
|
+
});
|
|
19
|
+
const colorVariant = instance.getEnum('Color', { default: 'default', error: 'error' });
|
|
20
|
+
const isLight = instance.getEnum('light', { true: true, false: false });
|
|
21
|
+
const color = isLight ? 'light' : colorVariant;
|
|
22
|
+
const disabled = instance.getEnum('State', {
|
|
23
|
+
default: false,
|
|
24
|
+
hover: false,
|
|
25
|
+
focus: false,
|
|
26
|
+
active: false,
|
|
27
|
+
disabled: true,
|
|
28
|
+
});
|
|
29
|
+
const iconOnly = instance.getEnum('Icon', { 'icon-only': true, text: false });
|
|
30
|
+
|
|
31
|
+
const structure = instance.findInstance('.button-structure', { traverseInstances: true });
|
|
32
|
+
const showIcon = structure.type === 'INSTANCE' ? structure.getBoolean('Show icon') : false;
|
|
33
|
+
|
|
34
|
+
// `DsButtonV3.icon` is an icon-name string. Swapped icons keep the placeholder layer
|
|
35
|
+
// name (e.g. `DAP_GM_O_check_circle`), so resolve via Code Connect ID or metadata.
|
|
36
|
+
const toIconName = (name: string): string =>
|
|
37
|
+
name
|
|
38
|
+
.replace(/^DAP_DAP_/, 'DAP_')
|
|
39
|
+
.replace(/^DAP_GM_[OS]_/, '')
|
|
40
|
+
.replace(/^DAP_outline_icon\//, '')
|
|
41
|
+
.replace(/^DAP_/, '')
|
|
42
|
+
.replace(/^\/+/, '')
|
|
43
|
+
.replace(/[\s/]+/g, '_')
|
|
44
|
+
.toLowerCase();
|
|
45
|
+
|
|
46
|
+
const iconNameFromCodeConnectId = (id: string | null): string | undefined => {
|
|
47
|
+
if (!id) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
if (id.startsWith('ds-icon-o-')) {
|
|
51
|
+
return id.slice('ds-icon-o-'.length);
|
|
52
|
+
}
|
|
53
|
+
if (id.startsWith('ds-icon-s-')) {
|
|
54
|
+
return id.slice('ds-icon-s-'.length);
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const resolveIcon = (iconInstance: figma.InstanceHandle): string | undefined => {
|
|
60
|
+
const fromCcId = iconNameFromCodeConnectId(iconInstance.codeConnectId());
|
|
61
|
+
if (fromCcId) {
|
|
62
|
+
return fromCcId;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const iconFromMetadata = iconInstance.executeTemplate().metadata?.props?.icon;
|
|
66
|
+
if (typeof iconFromMetadata === 'string') {
|
|
67
|
+
return iconFromMetadata;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return toIconName(iconInstance.name);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const leadingIcon = structure.type === 'INSTANCE' ? structure.getInstanceSwap('Leading icon') : undefined;
|
|
74
|
+
const iconFromSwap = leadingIcon?.type === 'INSTANCE' ? resolveIcon(leadingIcon) : undefined;
|
|
75
|
+
const iconFromChild =
|
|
76
|
+
structure.type === 'INSTANCE'
|
|
77
|
+
? structure
|
|
78
|
+
.findConnectedInstances((node) => node.codeConnectId()?.startsWith('ds-icon-') ?? false, {
|
|
79
|
+
traverseInstances: true,
|
|
80
|
+
})
|
|
81
|
+
.find((node): node is figma.InstanceHandle => node.type === 'INSTANCE')
|
|
82
|
+
: undefined;
|
|
83
|
+
const icon = iconFromSwap ?? (iconFromChild ? resolveIcon(iconFromChild) : undefined);
|
|
84
|
+
|
|
85
|
+
const labelNode = instance.findText('Button', { traverseInstances: true });
|
|
86
|
+
const label = labelNode.type === 'TEXT' ? labelNode.textContent : 'Button';
|
|
87
|
+
|
|
88
|
+
const iconProp = icon ? figma.code` icon="${icon}"` : '';
|
|
89
|
+
|
|
90
|
+
export default {
|
|
91
|
+
example: iconOnly
|
|
92
|
+
? figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}" ${disabled ? 'disabled' : ''}${iconProp} aria-label="${label}" />`
|
|
93
|
+
: showIcon && icon
|
|
94
|
+
? figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}" ${disabled ? 'disabled' : ''} icon="${icon}">${label}</DsButtonV3>`
|
|
95
|
+
: figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}" ${disabled ? 'disabled' : ''}>${label}</DsButtonV3>`,
|
|
96
|
+
imports: ["import { DsButtonV3 } from '@drivenets/design-system'"],
|
|
97
|
+
id: 'ds-button-v3',
|
|
98
|
+
metadata: { nestable: true },
|
|
99
|
+
};
|
|
@@ -293,66 +293,66 @@ $focus-ring-width: 2px;
|
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
.root[data-color='light'][data-variant='primary'] {
|
|
296
|
-
background-color: var(--background-
|
|
296
|
+
background-color: var(--background-light-primary);
|
|
297
297
|
color: var(--font-on-action);
|
|
298
298
|
border-color: transparent;
|
|
299
299
|
|
|
300
300
|
&:hover:not(:disabled):not(:active):not([data-selected='true']) {
|
|
301
|
-
background-color: var(--background-
|
|
301
|
+
background-color: var(--background-light-primary-hover);
|
|
302
302
|
}
|
|
303
303
|
|
|
304
304
|
&:active:not(:disabled) {
|
|
305
|
-
background-color: var(--background-
|
|
305
|
+
background-color: var(--background-light-primary-selected);
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
&:focus-visible {
|
|
309
|
-
@include focus-ring(var(--outline-
|
|
309
|
+
@include focus-ring(var(--outline-inverse));
|
|
310
310
|
|
|
311
|
-
background-color: var(--background-
|
|
311
|
+
background-color: var(--background-light-primary-hover);
|
|
312
312
|
border-color: var(--border-action-secondary);
|
|
313
313
|
}
|
|
314
314
|
|
|
315
315
|
&[data-selected='true'] {
|
|
316
|
-
background-color: var(--background-
|
|
316
|
+
background-color: var(--background-light-primary-selected);
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
&:disabled:not([data-loading]) {
|
|
320
|
-
background-color: var(--background-
|
|
321
|
-
color: var(--font-disabled);
|
|
320
|
+
background-color: var(--background-light-disabled);
|
|
321
|
+
color: var(--font-light-disabled);
|
|
322
322
|
}
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
.root[data-color='light'][data-variant='secondary'] {
|
|
326
326
|
background-color: transparent;
|
|
327
327
|
color: var(--font-on-action);
|
|
328
|
-
border-color: var(--border-
|
|
328
|
+
border-color: var(--border-light-secondary);
|
|
329
329
|
|
|
330
330
|
&:hover:not(:disabled):not(:active):not([data-selected='true']) {
|
|
331
|
-
background-color: var(--
|
|
331
|
+
background-color: var(--light-buttons-secondary-background);
|
|
332
332
|
color: var(--font-on-action);
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
&:active:not(:disabled) {
|
|
336
|
-
background-color: var(--background-
|
|
336
|
+
background-color: var(--background-light-secondary-selected);
|
|
337
337
|
color: var(--font-on-action);
|
|
338
338
|
}
|
|
339
339
|
|
|
340
340
|
&:focus-visible {
|
|
341
|
-
@include focus-ring(var(--outline-
|
|
341
|
+
@include focus-ring(var(--outline-inverse));
|
|
342
342
|
|
|
343
|
-
background-color: var(--
|
|
343
|
+
background-color: var(--light-buttons-secondary-background);
|
|
344
344
|
border-color: var(--border-action-secondary);
|
|
345
345
|
color: var(--font-on-action);
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
&[data-selected='true'] {
|
|
349
|
-
background-color: var(--background-
|
|
349
|
+
background-color: var(--background-light-secondary-selected);
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
&:disabled:not([data-loading]) {
|
|
353
353
|
background-color: transparent;
|
|
354
|
-
color: var(--font-
|
|
355
|
-
border-color: var(--
|
|
354
|
+
color: var(--font-light-disabled);
|
|
355
|
+
border-color: var(--border-light-disabled);
|
|
356
356
|
}
|
|
357
357
|
}
|
|
358
358
|
|
|
@@ -362,29 +362,29 @@ $focus-ring-width: 2px;
|
|
|
362
362
|
border-color: transparent;
|
|
363
363
|
|
|
364
364
|
&:hover:not(:disabled):not(:active):not([data-selected='true']) {
|
|
365
|
-
background-color: var(--
|
|
365
|
+
background-color: var(--light-buttons-secondary-background);
|
|
366
366
|
color: var(--font-on-action);
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
&:active:not(:disabled) {
|
|
370
|
-
background-color: var(--background-
|
|
370
|
+
background-color: var(--background-light-secondary-selected);
|
|
371
371
|
color: var(--font-on-action);
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
&:focus-visible {
|
|
375
|
-
@include focus-ring(var(--outline-
|
|
375
|
+
@include focus-ring(var(--outline-inverse));
|
|
376
376
|
|
|
377
|
-
background-color: var(--
|
|
377
|
+
background-color: var(--light-buttons-secondary-background);
|
|
378
378
|
border-color: var(--border-action-secondary);
|
|
379
379
|
color: var(--font-on-action);
|
|
380
380
|
}
|
|
381
381
|
|
|
382
382
|
&[data-selected='true'] {
|
|
383
|
-
background-color: var(--background-
|
|
383
|
+
background-color: var(--background-light-secondary-selected);
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
&:disabled:not([data-loading]) {
|
|
387
387
|
background-color: transparent;
|
|
388
|
-
color: var(--font-
|
|
388
|
+
color: var(--font-light-disabled);
|
|
389
389
|
}
|
|
390
390
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=28122-12357
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-card
|
|
3
|
+
// component=DsCard.Body
|
|
4
|
+
//
|
|
5
|
+
// `card content` maps to `DsCard.Body`. The section exposes no named slot — its
|
|
6
|
+
// content is a freeform `DAP_Content placeholder_v01` marker — so the children are
|
|
7
|
+
// a static placeholder. Expose a Figma slot on the section to forward real content.
|
|
8
|
+
import figma from 'figma';
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
example: figma.code`<DsCard.Body>Card content</DsCard.Body>`,
|
|
12
|
+
imports: ["import { DsCard } from '@drivenets/design-system'"],
|
|
13
|
+
id: 'ds-card-content',
|
|
14
|
+
metadata: { nestable: true },
|
|
15
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=28122-12361
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-card
|
|
3
|
+
// component=DsCard.Footer
|
|
4
|
+
//
|
|
5
|
+
// `card footer` maps to `DsCard.Footer`. The section exposes no named slot — its
|
|
6
|
+
// content is a freeform `DAP_Content placeholder_v01` marker — so the children are
|
|
7
|
+
// a static placeholder. Expose a Figma slot on the section to forward real content.
|
|
8
|
+
import figma from 'figma';
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
example: figma.code`<DsCard.Footer>Card footer</DsCard.Footer>`,
|
|
12
|
+
imports: ["import { DsCard } from '@drivenets/design-system'"],
|
|
13
|
+
id: 'ds-card-footer',
|
|
14
|
+
metadata: { nestable: true },
|
|
15
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=28122-12353
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-card
|
|
3
|
+
// component=DsCard.Header
|
|
4
|
+
//
|
|
5
|
+
// `card header` maps to `DsCard.Header`. The section exposes no named slot — its
|
|
6
|
+
// content is a freeform `DAP_Content placeholder_v01` marker — so the children are
|
|
7
|
+
// a static placeholder. Expose a Figma slot on the section to forward real content.
|
|
8
|
+
import figma from 'figma';
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
example: figma.code`<DsCard.Header>Card title</DsCard.Header>`,
|
|
12
|
+
imports: ["import { DsCard } from '@drivenets/design-system'"],
|
|
13
|
+
id: 'ds-card-header',
|
|
14
|
+
metadata: { nestable: true },
|
|
15
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=25703-1142
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-card
|
|
3
|
+
// component=DsCard
|
|
4
|
+
//
|
|
5
|
+
// `DAP_Card_v01` is the compound card. It maps to the composed `DsCard.Root` and
|
|
6
|
+
// resolves its `card header` / `card content` / `card footer` sections dynamically
|
|
7
|
+
// via their own Code Connect templates, so a section that is removed or restyled
|
|
8
|
+
// stays in sync. Sections are always present in the current design, but resolving
|
|
9
|
+
// them keeps a single source of truth for each slot.
|
|
10
|
+
import figma from 'figma';
|
|
11
|
+
|
|
12
|
+
const instance = figma.selectedInstance;
|
|
13
|
+
|
|
14
|
+
const size =
|
|
15
|
+
instance.getEnum('Size', {
|
|
16
|
+
Large: 'large',
|
|
17
|
+
Medium: 'medium',
|
|
18
|
+
Small: 'small',
|
|
19
|
+
}) ?? 'medium';
|
|
20
|
+
|
|
21
|
+
const state = instance.getEnum('State', {
|
|
22
|
+
default: 'default',
|
|
23
|
+
hover: 'default',
|
|
24
|
+
focus: 'default',
|
|
25
|
+
selected: 'selected',
|
|
26
|
+
'selected blue': 'highlighted',
|
|
27
|
+
disabled: 'disabled',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const selected = state === 'selected' || state === 'highlighted';
|
|
31
|
+
const highlightSelected = state === 'highlighted';
|
|
32
|
+
const disabled = state === 'disabled';
|
|
33
|
+
|
|
34
|
+
// A card is only selectable when it carries a selection state. Disabled is an
|
|
35
|
+
// independent modifier, so it must not imply `selectable` on its own.
|
|
36
|
+
const selectable = selected;
|
|
37
|
+
|
|
38
|
+
const flags = [
|
|
39
|
+
selectable && 'selectable',
|
|
40
|
+
selected && 'selected',
|
|
41
|
+
highlightSelected && 'highlightSelected',
|
|
42
|
+
disabled && 'disabled',
|
|
43
|
+
]
|
|
44
|
+
.filter(Boolean)
|
|
45
|
+
.join(' ');
|
|
46
|
+
|
|
47
|
+
const flagsAttr = flags ? ` ${flags}` : '';
|
|
48
|
+
|
|
49
|
+
const header = instance.findInstance('card header', { traverseInstances: true });
|
|
50
|
+
let headerCode: figma.ResultSection[] | undefined;
|
|
51
|
+
if (header.type === 'INSTANCE') {
|
|
52
|
+
headerCode = header.executeTemplate().example;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const content = instance.findInstance('card content', { traverseInstances: true });
|
|
56
|
+
let contentCode: figma.ResultSection[] | undefined;
|
|
57
|
+
if (content.type === 'INSTANCE') {
|
|
58
|
+
contentCode = content.executeTemplate().example;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const footer = instance.findInstance('card footer', { traverseInstances: true });
|
|
62
|
+
let footerCode: figma.ResultSection[] | undefined;
|
|
63
|
+
if (footer.type === 'INSTANCE') {
|
|
64
|
+
footerCode = footer.executeTemplate().example;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default {
|
|
68
|
+
example: figma.code`<DsCard.Root size="${size}"${flagsAttr}>${headerCode}${contentCode}${footerCode}</DsCard.Root>`,
|
|
69
|
+
imports: ["import { DsCard } from '@drivenets/design-system'"],
|
|
70
|
+
id: 'ds-card',
|
|
71
|
+
metadata: { nestable: false },
|
|
72
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=30063-134227
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-date-picker
|
|
3
|
+
// component=DsDatePicker
|
|
4
|
+
//
|
|
5
|
+
// `DAP_Date picker_v1.1` only exposes a `type` variant (day/month/year calendar view),
|
|
6
|
+
// which is internal UI state with no code-prop equivalent. The snippet is therefore an
|
|
7
|
+
// illustrative controlled-usage starter (props are not derived from Figma) showing the
|
|
8
|
+
// idiomatic `useState` + `value`/`onChange` pattern. `fcMember`/`fcProps` are surfaced so
|
|
9
|
+
// a parent `DsFormControl` template can render `<DsFormControl.DatePicker />`.
|
|
10
|
+
import figma from 'figma';
|
|
11
|
+
|
|
12
|
+
export default {
|
|
13
|
+
example: figma.code`const [value, setValue] = useState<Date | null>(null);
|
|
14
|
+
|
|
15
|
+
<DsDatePicker value={value} onChange={setValue} withTime placeholder="mm/dd/yyyy, hh:mm AM/PM" />`,
|
|
16
|
+
imports: ["import { useState } from 'react'", "import { DsDatePicker } from '@drivenets/design-system'"],
|
|
17
|
+
id: 'ds-date-picker',
|
|
18
|
+
metadata: { nestable: true, props: { fcMember: 'DatePicker', fcProps: '' } },
|
|
19
|
+
};
|
|
@@ -56,6 +56,20 @@
|
|
|
56
56
|
transform 0.2s ease,
|
|
57
57
|
width 0.2s ease;
|
|
58
58
|
|
|
59
|
+
// A closed (or closing) drawer is invisible but stays mounted and transformed.
|
|
60
|
+
// Without this it still hit-tests and can swallow clicks on neighboring UI when
|
|
61
|
+
// docked at a non-zero offset. Keep it click-through whenever it is not open.
|
|
62
|
+
//
|
|
63
|
+
// `!important` is required: when this drawer is stacked with other open Ark
|
|
64
|
+
// dialogs (e.g. a non-modal drawer opened over another dialog), Ark's layer
|
|
65
|
+
// management writes an inline `pointer-events: auto` onto the content, which
|
|
66
|
+
// would otherwise win over this rule and let the closed drawer keep eating
|
|
67
|
+
// clicks. Overriding a third-party inline style is the canonical use of
|
|
68
|
+
// `!important`, and a closed drawer must never be a pointer target.
|
|
69
|
+
&[data-state='closed'] {
|
|
70
|
+
pointer-events: none !important;
|
|
71
|
+
}
|
|
72
|
+
|
|
59
73
|
&.position-end {
|
|
60
74
|
right: 0;
|
|
61
75
|
transform-origin: 100% 50%;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CSSProperties, type ReactNode, Fragment } from 'react';
|
|
2
|
-
import { Dialog } from '@ark-ui/react/dialog';
|
|
2
|
+
import { Dialog, type DialogRootProps } from '@ark-ui/react/dialog';
|
|
3
3
|
import { Portal } from '@ark-ui/react/portal';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
import type { DsDrawerProps } from './ds-drawer.types';
|
|
@@ -12,6 +12,7 @@ import { useResponsiveValue } from '../../utils/responsive';
|
|
|
12
12
|
const DsDrawer = ({
|
|
13
13
|
open,
|
|
14
14
|
onOpenChange,
|
|
15
|
+
onOpenAutoFocus,
|
|
15
16
|
columns = 4,
|
|
16
17
|
position = 'end',
|
|
17
18
|
backdrop = false,
|
|
@@ -29,6 +30,23 @@ const DsDrawer = ({
|
|
|
29
30
|
onOpenChange(details.open);
|
|
30
31
|
};
|
|
31
32
|
|
|
33
|
+
// Mirrors Radix's `onOpenAutoFocus`. Ark reads `initialFocusEl` when the drawer
|
|
34
|
+
// opens to decide what to focus. To honor `preventDefault()`, we point initial
|
|
35
|
+
// focus back at the element that was focused when the drawer opened (e.g. the
|
|
36
|
+
// input that triggered it), so the caret stays put. Returning `undefined` keeps
|
|
37
|
+
// Ark's default of focusing the first element inside the drawer. The cast covers
|
|
38
|
+
// the `undefined` branch, which sits outside Ark's `MaybeElement` return type.
|
|
39
|
+
const initialFocusEl = (
|
|
40
|
+
onOpenAutoFocus
|
|
41
|
+
? () => {
|
|
42
|
+
const event = new Event('openAutoFocus', { cancelable: true });
|
|
43
|
+
onOpenAutoFocus(event);
|
|
44
|
+
|
|
45
|
+
return event.defaultPrevented ? (document.activeElement as HTMLElement | null) : undefined;
|
|
46
|
+
}
|
|
47
|
+
: undefined
|
|
48
|
+
) as DialogRootProps['initialFocusEl'];
|
|
49
|
+
|
|
32
50
|
const Wrapper = portal ? Portal : Fragment;
|
|
33
51
|
|
|
34
52
|
return (
|
|
@@ -39,6 +57,7 @@ const DsDrawer = ({
|
|
|
39
57
|
closeOnEscape={closeOnEscape}
|
|
40
58
|
closeOnInteractOutside={closeOnInteractOutside}
|
|
41
59
|
preventScroll={backdrop}
|
|
60
|
+
initialFocusEl={initialFocusEl}
|
|
42
61
|
>
|
|
43
62
|
<Wrapper>
|
|
44
63
|
{backdrop && <Dialog.Backdrop className={styles.backdrop} />}
|
|
@@ -20,6 +20,13 @@ export interface DsDrawerProps extends Pick<DialogProps, 'closeOnEscape' | 'clos
|
|
|
20
20
|
* Callback when the drawer open state changes
|
|
21
21
|
*/
|
|
22
22
|
onOpenChange: (open: boolean) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Called when focus is about to move into the drawer as it opens.
|
|
25
|
+
* Call `event.preventDefault()` to stop the drawer from stealing focus,
|
|
26
|
+
* keeping the caret where it was (e.g. in a text input that triggered the
|
|
27
|
+
* drawer). Useful for type-ahead / popover patterns.
|
|
28
|
+
*/
|
|
29
|
+
onOpenAutoFocus?: (event: Event) => void;
|
|
23
30
|
/**
|
|
24
31
|
* Number of grid columns the drawer should span (1-12).
|
|
25
32
|
* Accepts a responsive value, e.g. `{ lg: 4, md: 6 }`.
|
|
@@ -224,6 +224,13 @@ export function useFileUpload({
|
|
|
224
224
|
updateFileProgress(fileId, 100);
|
|
225
225
|
onFileUploadComplete?.(fileId, result);
|
|
226
226
|
} catch (error) {
|
|
227
|
+
// A fired abort signal means the upload was cancelled or removed by the
|
|
228
|
+
// user. Adapters reject with a (retryable) error on abort, but that must
|
|
229
|
+
// not overwrite the terminal status owned by cancelUpload/removeFile.
|
|
230
|
+
if (abortController.signal.aborted) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
227
234
|
const errorMessage = error instanceof Error ? error.message : 'Upload failed';
|
|
228
235
|
// Determine status based on error type
|
|
229
236
|
// Unknown errors are treated as retryable (network errors, etc.)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=13484-17388
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-form-control
|
|
3
|
+
// component=DsFormControl
|
|
4
|
+
//
|
|
5
|
+
// The Figma component `DAP_input/ input form unit/ vertical_v01` is the generic form-unit
|
|
6
|
+
// wrapper that owns the label, description and caption. Its `Swap Input to Select` slot
|
|
7
|
+
// holds the actual control (select, text/number/password input, ...), which is resolved
|
|
8
|
+
// dynamically. Inner templates that expose `metadata.props.fcMember` are linked as the
|
|
9
|
+
// idiomatic `DsFormControl.<member>` compound; anything else falls back to its bare snippet.
|
|
10
|
+
import figma from 'figma';
|
|
11
|
+
|
|
12
|
+
const instance = figma.selectedInstance;
|
|
13
|
+
|
|
14
|
+
const showLabel = instance.getBoolean('Show Label');
|
|
15
|
+
const showCaption = instance.getBoolean('Show Caption');
|
|
16
|
+
const showDescription = instance.getBoolean('Show Description');
|
|
17
|
+
const descriptionText = instance.getString('Description Text');
|
|
18
|
+
|
|
19
|
+
const labelInstance = instance.findInstance('input label', { traverseInstances: true });
|
|
20
|
+
const required = labelInstance.type === 'INSTANCE' ? labelInstance.getBoolean('Required') : false;
|
|
21
|
+
|
|
22
|
+
const labelText = instance.findText('Input label', { traverseInstances: true });
|
|
23
|
+
const label = labelText.type === 'TEXT' ? labelText.textContent : 'Label';
|
|
24
|
+
|
|
25
|
+
const captionInstance = instance.findInstance('inputs/ Input Caption', { traverseInstances: true });
|
|
26
|
+
const status =
|
|
27
|
+
captionInstance.type === 'INSTANCE'
|
|
28
|
+
? (captionInstance.getEnum('Status', {
|
|
29
|
+
Default: 'info',
|
|
30
|
+
Success: 'success',
|
|
31
|
+
Error: 'error',
|
|
32
|
+
Warning: 'warning',
|
|
33
|
+
}) ?? 'info')
|
|
34
|
+
: 'info';
|
|
35
|
+
|
|
36
|
+
// The caption text isn't bound to a component property, so read the first text layer
|
|
37
|
+
// inside the caption instance and pass it through as the `message` value.
|
|
38
|
+
const captionText =
|
|
39
|
+
captionInstance.type === 'INSTANCE'
|
|
40
|
+
? captionInstance.findLayers((node) => node.type === 'TEXT', { traverseInstances: true })[0]
|
|
41
|
+
: undefined;
|
|
42
|
+
const message = captionText?.type === 'TEXT' ? captionText.textContent : 'Caption';
|
|
43
|
+
|
|
44
|
+
// Resolve the swapped control and build the `DsFormControl.<member>` child from its
|
|
45
|
+
// surfaced metadata. Fall back to the bare snippet when no `fcMember` is exposed.
|
|
46
|
+
const inner = instance.getInstanceSwap('Swap Input to Select');
|
|
47
|
+
|
|
48
|
+
let child;
|
|
49
|
+
if (inner && inner.type === 'INSTANCE') {
|
|
50
|
+
const { example, metadata } = inner.executeTemplate();
|
|
51
|
+
const fcMember = metadata?.props?.fcMember;
|
|
52
|
+
const fcProps = metadata?.props?.fcProps ?? '';
|
|
53
|
+
|
|
54
|
+
child = fcMember ? figma.code`<DsFormControl.${fcMember} ${fcProps} />` : example;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const description = showDescription
|
|
58
|
+
? figma.code`<DsFormControl.Description>${descriptionText}</DsFormControl.Description>`
|
|
59
|
+
: '';
|
|
60
|
+
|
|
61
|
+
const labelAttr = `label="${label}"`;
|
|
62
|
+
const requiredAttr = required ? 'required' : '';
|
|
63
|
+
const hideLabelAttr = showLabel ? '' : 'hideLabel';
|
|
64
|
+
const statusAttr = status !== 'info' ? `status="${status}"` : '';
|
|
65
|
+
const messageAttr = showCaption ? `message="${message}"` : '';
|
|
66
|
+
|
|
67
|
+
const formControlAttrs = [labelAttr, requiredAttr, hideLabelAttr, statusAttr, messageAttr]
|
|
68
|
+
.filter(Boolean)
|
|
69
|
+
.join(' ');
|
|
70
|
+
|
|
71
|
+
export default {
|
|
72
|
+
example: figma.code`<DsFormControl ${formControlAttrs}>${description}${child}</DsFormControl>`,
|
|
73
|
+
imports: ["import { DsFormControl } from '@drivenets/design-system'"],
|
|
74
|
+
id: 'ds-form-control',
|
|
75
|
+
metadata: { nestable: false },
|
|
76
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import figma from 'figma';
|
|
2
|
+
|
|
3
|
+
const batch = figma.batch as { icon: string; filled: boolean; id: string };
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
example: figma.code`<DsIcon icon="${batch.icon}"${batch.filled ? ' filled' : ''} />`,
|
|
7
|
+
imports: ["import { DsIcon } from '@drivenets/design-system'"],
|
|
8
|
+
id: batch.id,
|
|
9
|
+
metadata: { nestable: true, props: { icon: batch.icon } },
|
|
10
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import figma from 'figma';
|
|
2
|
+
|
|
3
|
+
// Batch template for Figma special icon component sets (`special-*` icons),
|
|
4
|
+
// where a single `type` variant selects the icon. Variants without a `DsIcon`
|
|
5
|
+
// equivalent are absent from `typeMap`, so `getEnum` returns undefined for them.
|
|
6
|
+
const instance = figma.selectedInstance;
|
|
7
|
+
const batch = figma.batch as { id: string; variantProp: string; typeMap: Record<string, string> };
|
|
8
|
+
|
|
9
|
+
const icon = instance.getEnum(batch.variantProp, batch.typeMap);
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
example: icon
|
|
13
|
+
? figma.code`<DsIcon icon="${icon}" />`
|
|
14
|
+
: figma.code`{/* This icon is not available in @drivenets/design-system */}`,
|
|
15
|
+
imports: ["import { DsIcon } from '@drivenets/design-system'"],
|
|
16
|
+
id: batch.id,
|
|
17
|
+
metadata: { nestable: true, props: { icon } },
|
|
18
|
+
};
|