@vobs/ui 0.3.0 → 1.0.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.
Files changed (212) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +60 -0
  3. package/package.json +52 -110
  4. package/src/activity-rail.ts +125 -0
  5. package/src/alert.ts +65 -0
  6. package/src/assets/icons/alert-circle.svg +1 -0
  7. package/src/assets/icons/alert-triangle.svg +1 -0
  8. package/src/assets/icons/alert.d27e24.svg +1 -0
  9. package/src/assets/icons/alert.svg +1 -0
  10. package/src/assets/icons/apple.svg +1 -0
  11. package/src/assets/icons/arrow-down.svg +1 -0
  12. package/src/assets/icons/arrow-expand.svg +1 -0
  13. package/src/assets/icons/arrow-left.svg +1 -0
  14. package/src/assets/icons/arrow-minimize.svg +1 -0
  15. package/src/assets/icons/arrow-right-to-line.svg +1 -0
  16. package/src/assets/icons/arrow-right.svg +1 -0
  17. package/src/assets/icons/arrow-up-right.svg +1 -0
  18. package/src/assets/icons/arrow-up.0c0c0d.svg +1 -0
  19. package/src/assets/icons/arrow-up.svg +1 -0
  20. package/src/assets/icons/at.svg +1 -0
  21. package/src/assets/icons/atom.0c0c0d.svg +1 -0
  22. package/src/assets/icons/atom.svg +1 -0
  23. package/src/assets/icons/bar.svg +1 -0
  24. package/src/assets/icons/bell.svg +1 -0
  25. package/src/assets/icons/box.svg +1 -0
  26. package/src/assets/icons/bug.svg +1 -0
  27. package/src/assets/icons/calendar.svg +1 -0
  28. package/src/assets/icons/check-circle.33c192.svg +1 -0
  29. package/src/assets/icons/check-circle.svg +1 -0
  30. package/src/assets/icons/check.d1d3db.svg +1 -0
  31. package/src/assets/icons/check.svg +1 -0
  32. package/src/assets/icons/chevron-down.svg +1 -0
  33. package/src/assets/icons/chevron-right.svg +1 -0
  34. package/src/assets/icons/chevron-up.svg +1 -0
  35. package/src/assets/icons/circle.svg +1 -0
  36. package/src/assets/icons/clock.svg +1 -0
  37. package/src/assets/icons/cmd.svg +1 -0
  38. package/src/assets/icons/code.svg +1 -0
  39. package/src/assets/icons/columns.svg +1 -0
  40. package/src/assets/icons/copy.svg +1 -0
  41. package/src/assets/icons/cpu.svg +1 -0
  42. package/src/assets/icons/dashboard.0c0c0d.svg +1 -0
  43. package/src/assets/icons/dashboard.svg +1 -0
  44. package/src/assets/icons/dollar.svg +1 -0
  45. package/src/assets/icons/download.svg +1 -0
  46. package/src/assets/icons/edit.svg +1 -0
  47. package/src/assets/icons/extensions.svg +1 -0
  48. package/src/assets/icons/external.svg +1 -0
  49. package/src/assets/icons/eye.svg +1 -0
  50. package/src/assets/icons/file-text.svg +1 -0
  51. package/src/assets/icons/file.svg +1 -0
  52. package/src/assets/icons/files.svg +1 -0
  53. package/src/assets/icons/filter.svg +1 -0
  54. package/src/assets/icons/folder.svg +1 -0
  55. package/src/assets/icons/gear.svg +1 -0
  56. package/src/assets/icons/git.svg +1 -0
  57. package/src/assets/icons/github.svg +1 -0
  58. package/src/assets/icons/globe.svg +1 -0
  59. package/src/assets/icons/grid-2x2.svg +1 -0
  60. package/src/assets/icons/hash.svg +1 -0
  61. package/src/assets/icons/heart.svg +1 -0
  62. package/src/assets/icons/help.svg +1 -0
  63. package/src/assets/icons/home.svg +1 -0
  64. package/src/assets/icons/image.svg +1 -0
  65. package/src/assets/icons/info-circle.svg +1 -0
  66. package/src/assets/icons/info-square.svg +1 -0
  67. package/src/assets/icons/info.387bff.svg +1 -0
  68. package/src/assets/icons/info.svg +1 -0
  69. package/src/assets/icons/key.svg +1 -0
  70. package/src/assets/icons/layers.svg +1 -0
  71. package/src/assets/icons/layout.svg +1 -0
  72. package/src/assets/icons/link.svg +1 -0
  73. package/src/assets/icons/list.svg +1 -0
  74. package/src/assets/icons/lock.svg +1 -0
  75. package/src/assets/icons/log-out.svg +1 -0
  76. package/src/assets/icons/logo.svg +1 -0
  77. package/src/assets/icons/mail.svg +1 -0
  78. package/src/assets/icons/menu.svg +1 -0
  79. package/src/assets/icons/message-circle.svg +1 -0
  80. package/src/assets/icons/message-plus.svg +1 -0
  81. package/src/assets/icons/message-square.svg +1 -0
  82. package/src/assets/icons/mic.svg +1 -0
  83. package/src/assets/icons/minus.svg +1 -0
  84. package/src/assets/icons/moon.svg +1 -0
  85. package/src/assets/icons/more-h.svg +1 -0
  86. package/src/assets/icons/mouse.svg +1 -0
  87. package/src/assets/icons/palette.svg +1 -0
  88. package/src/assets/icons/panel-bottom.svg +1 -0
  89. package/src/assets/icons/pause.svg +1 -0
  90. package/src/assets/icons/play.svg +1 -0
  91. package/src/assets/icons/plug.svg +1 -0
  92. package/src/assets/icons/plus.0c0c0d.svg +1 -0
  93. package/src/assets/icons/plus.svg +1 -0
  94. package/src/assets/icons/refresh.svg +1 -0
  95. package/src/assets/icons/ruler.svg +1 -0
  96. package/src/assets/icons/scroll-text.svg +1 -0
  97. package/src/assets/icons/search-menu.svg +1 -0
  98. package/src/assets/icons/search.svg +1 -0
  99. package/src/assets/icons/send.0c0c0d.svg +1 -0
  100. package/src/assets/icons/send.svg +1 -0
  101. package/src/assets/icons/settings.0c0c0d.svg +1 -0
  102. package/src/assets/icons/settings.svg +1 -0
  103. package/src/assets/icons/shield.svg +1 -0
  104. package/src/assets/icons/sidebar-left.svg +1 -0
  105. package/src/assets/icons/sidebar-right.svg +1 -0
  106. package/src/assets/icons/sliders.svg +1 -0
  107. package/src/assets/icons/sparkles.32f08c.svg +1 -0
  108. package/src/assets/icons/sparkles.svg +1 -0
  109. package/src/assets/icons/square.svg +1 -0
  110. package/src/assets/icons/star.svg +1 -0
  111. package/src/assets/icons/sun.svg +1 -0
  112. package/src/assets/icons/terminal.svg +1 -0
  113. package/src/assets/icons/trash.svg +1 -0
  114. package/src/assets/icons/trending-down.svg +1 -0
  115. package/src/assets/icons/trending-up.svg +1 -0
  116. package/src/assets/icons/type.svg +1 -0
  117. package/src/assets/icons/upload.svg +1 -0
  118. package/src/assets/icons/user-circle.svg +1 -0
  119. package/src/assets/icons/user.svg +1 -0
  120. package/src/assets/icons/users.svg +1 -0
  121. package/src/assets/icons/wrench.svg +1 -0
  122. package/src/assets/icons/x-circle.svg +1 -0
  123. package/src/assets/icons/x.svg +1 -0
  124. package/src/assets/icons/zap.0c0c0d.svg +1 -0
  125. package/src/assets/icons/zap.svg +1 -0
  126. package/src/avatar.ts +64 -0
  127. package/src/button.ts +88 -0
  128. package/src/card.ts +59 -0
  129. package/src/chat-composer.ts +156 -0
  130. package/src/dialog.ts +127 -0
  131. package/src/drawer.ts +131 -0
  132. package/src/editor-tabs.ts +184 -0
  133. package/src/file-tree.ts +214 -0
  134. package/src/forms.ts +270 -0
  135. package/src/icon.ts +117 -0
  136. package/src/icons.js +165 -0
  137. package/src/index.test.ts +213 -0
  138. package/src/index.ts +94 -0
  139. package/src/kbd.ts +72 -0
  140. package/src/menu.ts +119 -0
  141. package/src/nav-list.ts +157 -0
  142. package/src/overlay.test.ts +66 -0
  143. package/src/overlay.ts +205 -0
  144. package/src/page-header.ts +97 -0
  145. package/src/pagination.ts +163 -0
  146. package/src/second-batch.test.ts +205 -0
  147. package/src/stat-card.ts +92 -0
  148. package/src/status-bar.ts +108 -0
  149. package/src/styles/base.css +240 -0
  150. package/src/styles/components.css +1234 -0
  151. package/{dist → src/styles}/styles.css +2 -0
  152. package/src/styles/toast.css +57 -0
  153. package/src/styles/tokens.css +438 -0
  154. package/src/styles/vui.css +47 -0
  155. package/src/table.ts +191 -0
  156. package/src/tabs.ts +100 -0
  157. package/src/tag.ts +33 -0
  158. package/src/third-batch.test.ts +137 -0
  159. package/src/toast.test.ts +55 -0
  160. package/src/toast.ts +79 -0
  161. package/src/types.ts +25 -0
  162. package/src/utils.ts +221 -0
  163. package/src/workbench-titlebar.ts +137 -0
  164. package/dist/app-shell-dom.d.ts +0 -30
  165. package/dist/app-shell-dom.js +0 -913
  166. package/dist/app-shell.d.ts +0 -235
  167. package/dist/app-shell.js +0 -415
  168. package/dist/base.css +0 -51
  169. package/dist/calendar-picker.d.ts +0 -45
  170. package/dist/calendar-picker.js +0 -217
  171. package/dist/calendar.d.ts +0 -95
  172. package/dist/calendar.js +0 -194
  173. package/dist/complex-inputs.d.ts +0 -300
  174. package/dist/complex-inputs.js +0 -866
  175. package/dist/components.css +0 -4756
  176. package/dist/data-display.d.ts +0 -1094
  177. package/dist/data-display.js +0 -2341
  178. package/dist/dialog.d.ts +0 -26
  179. package/dist/dialog.js +0 -94
  180. package/dist/feedback.d.ts +0 -88
  181. package/dist/feedback.js +0 -281
  182. package/dist/forms.d.ts +0 -378
  183. package/dist/forms.js +0 -1019
  184. package/dist/icons-config.d.ts +0 -25
  185. package/dist/icons-config.js +0 -14
  186. package/dist/icons.d.ts +0 -41
  187. package/dist/icons.js +0 -185
  188. package/dist/index.d.ts +0 -31
  189. package/dist/index.js +0 -40
  190. package/dist/locale/en-US.d.ts +0 -31
  191. package/dist/locale/en-US.js +0 -20
  192. package/dist/locale/zh-CN.d.ts +0 -31
  193. package/dist/locale/zh-CN.js +0 -20
  194. package/dist/navigation.d.ts +0 -609
  195. package/dist/navigation.js +0 -1707
  196. package/dist/overlay.d.ts +0 -308
  197. package/dist/overlay.js +0 -974
  198. package/dist/page-state.d.ts +0 -23
  199. package/dist/page-state.js +0 -96
  200. package/dist/primitives.d.ts +0 -268
  201. package/dist/primitives.js +0 -764
  202. package/dist/theme-data.d.ts +0 -394
  203. package/dist/theme-data.js +0 -417
  204. package/dist/theme.d.ts +0 -97
  205. package/dist/theme.js +0 -301
  206. package/dist/tokens.css +0 -570
  207. package/dist/tree.d.ts +0 -144
  208. package/dist/tree.js +0 -475
  209. package/dist/virtual-list.d.ts +0 -190
  210. package/dist/virtual-list.js +0 -538
  211. package/dist/workbench.d.ts +0 -136
  212. package/dist/workbench.js +0 -156
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 vobsjs
3
+ Copyright (c) 2026 vobs contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # @vobs/ui
2
+
3
+ Signal-driven component library for the vobs framework: run-once components compiled from JSX by `@vobs/vite-plugin`, styled through the `vui-` class contract, with portal-based overlays and focus management.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @vobs/ui
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```ts
14
+ import { state } from '@vobs/reactivity'
15
+ import { createComponent, createDOMRenderer, createVobs, setRenderer } from '@vobs/vobs'
16
+ import { Dialog } from '@vobs/ui'
17
+
18
+ setRenderer(createDOMRenderer())
19
+
20
+ const open = state(true)
21
+
22
+ const app = createVobs({
23
+ render: () => createComponent(Dialog, {
24
+ get open() { return open.value },
25
+ title: 'Confirm',
26
+ onClose: reason => { open.value = false },
27
+ children: 'Delete this item?'
28
+ })
29
+ })
30
+
31
+ app.mount(document.getElementById('app')!)
32
+ ```
33
+
34
+ The surface renders inside the component placeholder by default and through a portal when `portal`/`portalTarget` are provided. `onClose` receives a `DialogCloseReason` (`'close-button' | 'backdrop' | 'escape'`); Escape closes the surface while `closeOnEscape` is not disabled.
35
+
36
+ ## API
37
+
38
+ | Signature | Description |
39
+ | --- | --- |
40
+ | `Button(props?: ButtonProps)` | Button with reactive `disabled`/`loading` (`aria-busy`), `variant`, external `icon` and `children` nodes. `ButtonGroup(props?)` groups related buttons. |
41
+ | `Input(props?)`, `Textarea(props?)`, `Select(props?)`, `Checkbox(props?)`, `Radio(props?)`, `Switch(props?)` | Form controls wired to a controlled `value` plus `onInput`/`onChange` callbacks. |
42
+ | `Card(props?)`, `CardHeader(props?)` | Content container with `title` and `description` slots. |
43
+ | `Tag(props?)`, `Alert(props?)`, `Avatar(props?)`, `Kbd(props?)`, `KbdCombo(props?)`, `KbdRow(props?)` | Presentational components with tone and size props. |
44
+ | `Tabs(props: TabsProps)` | Tab bar and panels; uncontrolled activation updates and notifies via `onChange`. |
45
+ | `Dialog(props?)`, `Drawer(props?)` | Modal surfaces: `aria-modal`, portal mounting, close-button/backdrop/Escape close reasons. |
46
+ | `Menu(props?)`, `MenuDivider(props?)`, `NavList(props?)`, `Pagination(props?)`, `PageHeader(props?)`, `PageHeaderAction(props?)` | Navigation and page furniture. |
47
+ | `Table<Row>(props?)`, `TablePanel<Row>(props?)` | Base table rendering; `@vobs/table` builds its data table on top. |
48
+ | `StatCard(props?)`, `StatCardGrid(props?)`, `ActivityRail(props?)`, `FileTree(props?)`, `EditorTabs(props?)`, `WorkbenchTitlebar(props?)`, `StatusBar(props?)`, `ChatComposer(props?)` | Workbench-style building blocks. |
49
+ | `ToastHost(props?)` | Toast viewport with `ToastPosition`. |
50
+ | `createPortal(node, adapter, target)` | Mounts `node` outside the component placeholder; unmounts when the owning component is disposed. |
51
+ | `createDOMPortalAdapter()` | `VuiPortalAdapter` that appends and removes DOM nodes. |
52
+ | `createFocusTrap(root, options?)` | Cycles Tab within `root` and restores the previously focused element on `deactivate()`. Options: `initialFocus`, `restoreFocus`, `onEscape`. |
53
+ | `createOverlayManager()` | Overlay stack of `OverlayEntry` items with `open`, `close`, `bringToFront`, `subscribe`, and `entries`. |
54
+ | `Icon(props?)` | Built-in SVG icon by `name` with `size`/`title`; `createIcon`, `registerIcon`, `resolveIcon`, and `VUI_ICON_PATHS` manage the definition registry backed by `@vobs/icon-core`. |
55
+
56
+ Components accept plain values, signals, or getters for reactive props, and merge consumer `class`/`className` into the `vui-` class list without leaking it to inner elements.
57
+
58
+ ## Types
59
+
60
+ ButtonProps, ButtonVariant, ButtonGroupProps, ControlSize, ChoiceProps, InputProps, InputType, SelectProps, SwitchProps, TextareaProps, CardProps, CardHeaderProps, TagProps, TagTone, AlertProps, AlertTone, TabItem, TabsProps, DialogCloseReason, DialogProps, MenuItem, MenuProps, NavGroup, NavItem, NavListProps, PaginationProps, AvatarProps, AvatarShape, AvatarSize, PageHeaderActionProps, PageHeaderProps, TableAlign, TableColumn, TablePanelProps, TableProps, StatCardGridProps, StatCardProps, StatDeltaDirection, KbdComboProps, KbdProps, KbdRowProps, ActivityRailItem, ActivityRailProps, FileTreeItem, FileTreeItemKind, FileTreeProps, EditorTabItem, EditorTabsProps, WorkbenchTitlebarProps, StatusBarDot, StatusBarItem, StatusBarProps, ChatComposerProps, DrawerCloseReason, DrawerProps, ToastHostProps, ToastPosition, FocusTrapHandle, FocusTrapOptions, OverlayEntry, OverlayManager, VuiPortalAdapter, IconDefinition, IconProps, VuiAttributeValue, VuiChildren, VuiCommonProps, VuiEventHandler
package/package.json CHANGED
@@ -1,121 +1,63 @@
1
1
  {
2
- "name": "@vobs/ui",
3
- "version": "0.3.0",
4
- "description": "Optional design tokens, layouts and UI components for vobs.",
5
- "type": "module",
6
- "publishConfig": {
7
- "access": "public"
8
- },
9
2
  "license": "MIT",
10
- "author": "vobsjs",
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/vobsjs/vobs.git",
14
- "directory": "packages/features/ui"
15
- },
16
- "bugs": {
17
- "url": "https://github.com/vobsjs/vobs/issues"
18
- },
19
- "homepage": "https://github.com/vobsjs/vobs#readme",
20
3
  "files": [
21
- "dist"
4
+ "src",
5
+ "README.md",
6
+ "LICENSE"
22
7
  ],
8
+ "name": "@vobs/ui",
9
+ "version": "1.0.0",
10
+ "description": "Optional UI components and UIStyle-compatible styles for Vobs.",
11
+ "type": "module",
12
+ "main": "src/index.ts",
13
+ "types": "src/index.ts",
23
14
  "exports": {
24
- ".": {
25
- "types": "./dist/index.d.ts",
26
- "import": "./dist/index.js"
27
- },
28
- "./feedback": {
29
- "types": "./dist/feedback.d.ts",
30
- "import": "./dist/feedback.js"
31
- },
32
- "./app-shell": {
33
- "types": "./dist/app-shell.d.ts",
34
- "import": "./dist/app-shell.js"
35
- },
36
- "./complex-inputs": {
37
- "types": "./dist/complex-inputs.d.ts",
38
- "import": "./dist/complex-inputs.js"
39
- },
40
- "./data-display": {
41
- "types": "./dist/data-display.d.ts",
42
- "import": "./dist/data-display.js"
43
- },
44
- "./page-state": {
45
- "types": "./dist/page-state.d.ts",
46
- "import": "./dist/page-state.js"
47
- },
48
- "./dialog": {
49
- "types": "./dist/dialog.d.ts",
50
- "import": "./dist/dialog.js"
51
- },
52
- "./icons": {
53
- "types": "./dist/icons.d.ts",
54
- "import": "./dist/icons.js"
55
- },
56
- "./icons/config": {
57
- "types": "./dist/icons-config.d.ts",
58
- "import": "./dist/icons-config.js"
59
- },
60
- "./forms": {
61
- "types": "./dist/forms.d.ts",
62
- "import": "./dist/forms.js"
63
- },
64
- "./overlay": {
65
- "types": "./dist/overlay.d.ts",
66
- "import": "./dist/overlay.js"
67
- },
68
- "./navigation": {
69
- "types": "./dist/navigation.d.ts",
70
- "import": "./dist/navigation.js"
71
- },
72
- "./primitives": {
73
- "types": "./dist/primitives.d.ts",
74
- "import": "./dist/primitives.js"
75
- },
76
- "./locale/en-US": {
77
- "types": "./dist/locale/en-US.d.ts",
78
- "import": "./dist/locale/en-US.js"
79
- },
80
- "./locale/zh-CN": {
81
- "types": "./dist/locale/zh-CN.d.ts",
82
- "import": "./dist/locale/zh-CN.js"
83
- },
84
- "./theme": {
85
- "types": "./dist/theme.d.ts",
86
- "import": "./dist/theme.js"
87
- },
88
- "./tree": {
89
- "types": "./dist/tree.d.ts",
90
- "import": "./dist/tree.js"
91
- },
92
- "./virtual-list": {
93
- "types": "./dist/virtual-list.d.ts",
94
- "import": "./dist/virtual-list.js"
95
- },
96
- "./tokens.css": "./dist/tokens.css",
97
- "./base.css": "./dist/base.css",
98
- "./components.css": "./dist/components.css",
99
- "./styles.css": "./dist/styles.css",
15
+ ".": "./src/index.ts",
16
+ "./button": "./src/button.ts",
17
+ "./forms": "./src/forms.ts",
18
+ "./card": "./src/card.ts",
19
+ "./tag": "./src/tag.ts",
20
+ "./alert": "./src/alert.ts",
21
+ "./tabs": "./src/tabs.ts",
22
+ "./dialog": "./src/dialog.ts",
23
+ "./icon": "./src/icon.ts",
24
+ "./menu": "./src/menu.ts",
25
+ "./nav-list": "./src/nav-list.ts",
26
+ "./pagination": "./src/pagination.ts",
27
+ "./avatar": "./src/avatar.ts",
28
+ "./page-header": "./src/page-header.ts",
29
+ "./table": "./src/table.ts",
30
+ "./stat-card": "./src/stat-card.ts",
31
+ "./kbd": "./src/kbd.ts",
32
+ "./activity-rail": "./src/activity-rail.ts",
33
+ "./file-tree": "./src/file-tree.ts",
34
+ "./editor-tabs": "./src/editor-tabs.ts",
35
+ "./workbench-titlebar": "./src/workbench-titlebar.ts",
36
+ "./status-bar": "./src/status-bar.ts",
37
+ "./chat-composer": "./src/chat-composer.ts",
38
+ "./drawer": "./src/drawer.ts",
39
+ "./toast": "./src/toast.ts",
40
+ "./toast.css": "./src/styles/toast.css",
41
+ "./overlay": "./src/overlay.ts",
42
+ "./icons.js": "./src/icons.js",
43
+ "./assets/icons/*": "./src/assets/icons/*",
44
+ "./tokens.css": "./src/styles/tokens.css",
45
+ "./base.css": "./src/styles/base.css",
46
+ "./components.css": "./src/styles/components.css",
47
+ "./vui.css": "./src/styles/vui.css",
48
+ "./styles.css": "./src/styles/styles.css",
100
49
  "./package.json": "./package.json"
101
50
  },
102
- "types": "./dist/index.d.ts",
103
- "module": "./dist/index.js",
104
- "main": "./dist/index.js",
105
- "dependencies": {
106
- "@tanstack/virtual-core": "^3.17.7",
107
- "@vobs/icons": "0.3.0",
108
- "@vobs/i18n": "0.3.0",
109
- "@vobs/forms": "0.3.0",
110
- "@vobs/runtime-dom": "0.3.0",
111
- "@vobs/router": "0.3.0",
112
- "@vobs/reactivity": "0.3.0",
113
- "@vobs/server-renderer": "0.3.0"
114
- },
115
51
  "sideEffects": [
116
- "./dist/*.css"
52
+ "./src/styles/*.css"
117
53
  ],
118
- "engines": {
119
- "node": ">=22.12.0"
54
+ "dependencies": {
55
+ "@vobs/icon-core": "1.0.0",
56
+ "@vobs/vobs": "1.0.0",
57
+ "@vobs/reactivity": "1.0.0",
58
+ "@vobs/notification": "1.0.0"
59
+ },
60
+ "scripts": {
61
+ "test": "vitest --environment jsdom"
120
62
  }
121
63
  }
@@ -0,0 +1,125 @@
1
+ import { state } from '@vobs/reactivity'
2
+ import {
3
+ addEventListener,
4
+ createElement,
5
+ createFragment,
6
+ createText,
7
+ insertBefore,
8
+ insertDynamic,
9
+ setAttribute,
10
+ setProperty,
11
+ type VobsNode
12
+ } from '@vobs/vobs'
13
+ import {
14
+ bindClassList,
15
+ bindCommonAttributes,
16
+ bindUserStyle,
17
+ hasProp,
18
+ mountSlot,
19
+ readProp,
20
+ setOptionalAttribute
21
+ } from './utils'
22
+ import type { VuiChildren, VuiCommonProps } from './types'
23
+
24
+ export interface ActivityRailItem {
25
+ readonly id?: string
26
+ readonly label?: string
27
+ readonly icon?: VuiChildren
28
+ readonly divider?: boolean
29
+ readonly spacer?: boolean
30
+ readonly disabled?: boolean
31
+ }
32
+
33
+ export interface ActivityRailProps extends VuiCommonProps {
34
+ readonly items?: readonly ActivityRailItem[]
35
+ readonly value?: string
36
+ readonly defaultValue?: string
37
+ readonly onChange?: (id: string, event: MouseEvent) => void
38
+ }
39
+
40
+ export function ActivityRail(props: ActivityRailProps = {}): VobsNode {
41
+ const root = createElement('nav')
42
+ const internalValue = state<string | undefined>(undefined)
43
+ bindClassList(root, props, () => ['vui-activityrail'])
44
+ bindCommonAttributes(root, props, ['items', 'value', 'defaultValue', 'onChange'])
45
+ bindUserStyle(root, props)
46
+ if (!hasProp(props, 'aria-label')) setAttribute(root, 'aria-label', 'Activity')
47
+ if (hasProp(props, 'items')) insertDynamic(root, null, () => createActivityItems(props, internalValue))
48
+ if (hasProp(props, 'children')) mountSlot(root, props, 'children')
49
+ return root
50
+ }
51
+
52
+ function createActivityItems(
53
+ props: ActivityRailProps,
54
+ internalValue: { value: string | undefined }
55
+ ): VobsNode {
56
+ const items = readProp<readonly ActivityRailItem[]>(props, 'items', [])
57
+ const selected = activeId(props, items, internalValue)
58
+ return createFragment((parent, anchor) => {
59
+ for (const item of items) {
60
+ if (item.divider === true) {
61
+ const divider = createElement('div')
62
+ setAttribute(divider, 'class', 'vui-activityrail__divider')
63
+ setAttribute(divider, 'role', 'separator')
64
+ insertBefore(parent, divider, anchor)
65
+ continue
66
+ }
67
+ if (item.spacer === true) {
68
+ const spacer = createElement('span')
69
+ setAttribute(spacer, 'class', 'vui-activityrail__spacer')
70
+ insertBefore(parent, spacer, anchor)
71
+ continue
72
+ }
73
+ insertBefore(parent, createActivityButton(item, props, selected, internalValue), anchor)
74
+ }
75
+ })
76
+ }
77
+
78
+ function createActivityButton(
79
+ item: ActivityRailItem,
80
+ props: ActivityRailProps,
81
+ selected: string | undefined,
82
+ internalValue: { value: string | undefined }
83
+ ): VobsNode {
84
+ const button = createElement('button')
85
+ const active = item.id !== undefined && item.id === selected
86
+ setAttribute(button, 'class', `vui-activityrail__btn${active ? ' is-active' : ''}`)
87
+ setAttribute(button, 'type', 'button')
88
+ setOptionalAttribute(button, 'aria-label', item.label)
89
+ setOptionalAttribute(button, 'title', item.label)
90
+ setAttribute(button, 'aria-pressed', active ? 'true' : 'false')
91
+ if (item.disabled === true) {
92
+ setProperty(button, 'disabled', true)
93
+ setAttribute(button, 'aria-disabled', 'true')
94
+ }
95
+
96
+ if (item.icon !== undefined) {
97
+ const icon = createElement('span')
98
+ setAttribute(icon, 'class', 'vui-activityrail__icon')
99
+ mountSlot(icon, item, 'icon')
100
+ insertBefore(button, icon, null)
101
+ } else if (item.label !== undefined) {
102
+ insertBefore(button, createText(item.label), null)
103
+ }
104
+
105
+ addEventListener(button, 'click', event => {
106
+ if (item.disabled === true || item.id === undefined) return
107
+ if (readProp<string | undefined>(props, 'value', undefined) === undefined) internalValue.value = item.id
108
+ const handler = readProp<unknown>(props, 'onChange', undefined)
109
+ if (typeof handler === 'function') (handler as ActivityRailProps['onChange'])!(item.id, event as MouseEvent)
110
+ })
111
+ return button
112
+ }
113
+
114
+ function activeId(
115
+ props: ActivityRailProps,
116
+ items: readonly ActivityRailItem[],
117
+ internalValue: { value: string | undefined }
118
+ ): string | undefined {
119
+ const controlled = readProp<string | undefined>(props, 'value', undefined)
120
+ if (controlled !== undefined) return controlled
121
+ if (internalValue.value !== undefined) return internalValue.value
122
+ const defaultValue = readProp<string | undefined>(props, 'defaultValue', undefined)
123
+ if (defaultValue !== undefined) return defaultValue
124
+ return items.find(item => item.id !== undefined)?.id
125
+ }
package/src/alert.ts ADDED
@@ -0,0 +1,65 @@
1
+ import {
2
+ createElement,
3
+ createText,
4
+ insertBefore,
5
+ setAttribute,
6
+ type VobsNode
7
+ } from '@vobs/vobs'
8
+ import {
9
+ bindClassList,
10
+ bindCommonAttributes,
11
+ bindTextContent,
12
+ bindUserStyle,
13
+ hasProp,
14
+ mountSlot,
15
+ readProp
16
+ } from './utils'
17
+ import type { VuiCommonProps } from './types'
18
+
19
+ export type AlertTone = 'info' | 'success' | 'warning' | 'danger'
20
+
21
+ export interface AlertProps extends VuiCommonProps {
22
+ readonly tone?: AlertTone
23
+ readonly title?: string
24
+ readonly description?: string
25
+ readonly icon?: VobsNode | (() => VobsNode | null | undefined)
26
+ }
27
+
28
+ export function Alert(props: AlertProps = {}): VobsNode {
29
+ const root = createElement('div')
30
+ bindClassList(root, props, () => [
31
+ 'vui-alert',
32
+ `vui-alert--${readProp<AlertTone>(props, 'tone', 'info')}`
33
+ ])
34
+ bindCommonAttributes(root, props, ['tone', 'title', 'description', 'icon', 'role'])
35
+ bindUserStyle(root, props)
36
+ setAttribute(root, 'role', 'alert')
37
+
38
+ if (hasProp(props, 'icon')) {
39
+ const icon = createElement('span')
40
+ setAttribute(icon, 'class', 'vui-alert__icon')
41
+ mountSlot(icon, props, 'icon')
42
+ insertBefore(root, icon, null)
43
+ }
44
+
45
+ const content = createElement('div')
46
+ if (hasProp(props, 'title')) {
47
+ const title = createElement('div')
48
+ const text = createText('')
49
+ setAttribute(title, 'class', 'vui-alert__title')
50
+ bindTextContent(text, () => readProp(props, 'title', ''))
51
+ insertBefore(title, text, null)
52
+ insertBefore(content, title, null)
53
+ }
54
+ if (hasProp(props, 'description')) {
55
+ const description = createElement('div')
56
+ const text = createText('')
57
+ setAttribute(description, 'class', 'vui-alert__desc')
58
+ bindTextContent(text, () => readProp(props, 'description', ''))
59
+ insertBefore(description, text, null)
60
+ insertBefore(content, description, null)
61
+ }
62
+ if (hasProp(props, 'children')) mountSlot(content, props, 'children')
63
+ insertBefore(root, content, null)
64
+ return root
65
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><circle cx="12" cy="12" r="9"/><line x1="12" y1="8" x2="12" y2="13"/><line x1="12" y1="16" x2="12" y2="16.01"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><path d="M12 3 22 20 2 20 Z"/><line x1="12" y1="10" x2="12" y2="15"/><line x1="12" y1="18" x2="12" y2="18.01"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D27E24" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><path d="M12 3 22 20 2 20 Z"/><line x1="12" y1="10" x2="12" y2="15"/><line x1="12" y1="18" x2="12" y2="18.01"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><path d="M12 3 22 20 2 20 Z"/><line x1="12" y1="10" x2="12" y2="15"/><line x1="12" y1="18" x2="12" y2="18.01"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><path fill="#D1D3DB" stroke="none" d="M17.05 12.04c-.03-3.04 2.49-4.5 2.6-4.57-1.42-2.07-3.62-2.36-4.4-2.39-1.87-.19-3.65 1.1-4.6 1.1-.96 0-2.42-1.08-3.98-1.05-2.05.03-3.94 1.19-4.99 3.02-2.13 3.69-.54 9.13 1.53 12.12 1.01 1.46 2.21 3.1 3.78 3.04 1.52-.06 2.09-.98 3.93-.98 1.83 0 2.36.98 3.97.95 1.64-.03 2.68-1.49 3.68-2.96 1.16-1.7 1.64-3.35 1.66-3.43-.04-.02-3.18-1.22-3.21-4.85zM14.06 4.34c.83-1.01 1.39-2.41 1.24-3.81-1.2.05-2.65.8-3.51 1.8-.77.89-1.45 2.31-1.27 3.68 1.34.1 2.71-.68 3.54-1.67z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><line x1="12" y1="4" x2="12" y2="20"/><polyline points="6 14 12 20 18 14"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="14 4 20 4 20 10"/><line x1="14" y1="10" x2="20" y2="4"/><polyline points="10 20 4 20 4 14"/><line x1="10" y1="14" x2="4" y2="20"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><line x1="20" y1="12" x2="4" y2="12"/><polyline points="10 6 4 12 10 18"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="20 4 14 10 20 10"/><line x1="14" y1="10" x2="14" y2="4"/><polyline points="4 20 10 14 4 14"/><line x1="10" y1="14" x2="10" y2="20"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><line x1="20" y1="4" x2="20" y2="20"/><line x1="3" y1="12" x2="17" y2="12"/><polyline points="11 6 17 12 11 18"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><line x1="4" y1="12" x2="20" y2="12"/><polyline points="14 6 20 12 14 18"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><line x1="6" y1="18" x2="18" y2="6"/><polyline points="9 6 18 6 18 15"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#0C0C0D" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><line x1="12" y1="20" x2="12" y2="4"/><polyline points="6 10 12 4 18 10"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><line x1="12" y1="20" x2="12" y2="4"/><polyline points="6 10 12 4 18 10"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#0C0C0D" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><circle cx="12" cy="12" r="2"/><ellipse cx="12" cy="12" rx="10" ry="4"/><ellipse cx="12" cy="12" rx="10" ry="4" transform="rotate(60 12 12)"/><ellipse cx="12" cy="12" rx="10" ry="4" transform="rotate(120 12 12)"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><circle cx="12" cy="12" r="2"/><ellipse cx="12" cy="12" rx="10" ry="4"/><ellipse cx="12" cy="12" rx="10" ry="4" transform="rotate(60 12 12)"/><ellipse cx="12" cy="12" rx="10" ry="4" transform="rotate(120 12 12)"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><line x1="3" y1="21" x2="21" y2="21"/><rect x="5" y="11" width="3" height="8"/><rect x="10.5" y="6" width="3" height="13"/><rect x="16" y="14" width="3" height="5"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 8 3 8H3s3-1 3-8z"/><path d="M10 21a2 2 0 0 0 4 0"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="3 7 12 2 21 7 21 17 12 22 3 17 3 7"/><line x1="3" y1="7" x2="12" y2="12"/><line x1="21" y1="7" x2="12" y2="12"/><line x1="12" y1="22" x2="12" y2="12"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><rect x="8" y="6" width="8" height="14" rx="4"/><line x1="12" y1="11" x2="12" y2="20"/><line x1="3" y1="9" x2="8" y2="9"/><line x1="3" y1="14" x2="8" y2="14"/><line x1="3" y1="19" x2="8" y2="19"/><line x1="16" y1="9" x2="21" y2="9"/><line x1="16" y1="14" x2="21" y2="14"/><line x1="16" y1="19" x2="21" y2="19"/><line x1="9" y1="6" x2="9" y2="3"/><line x1="15" y1="6" x2="15" y2="3"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><rect x="3" y="5" width="18" height="16"/><line x1="3" y1="10" x2="21" y2="10"/><line x1="8" y1="3" x2="8" y2="7"/><line x1="16" y1="3" x2="16" y2="7"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#33C192" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><circle cx="12" cy="12" r="9"/><polyline points="8 12 11 15 16 9"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><circle cx="12" cy="12" r="9"/><polyline points="8 12 11 15 16 9"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="4 12 10 18 20 6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="4 12 10 18 20 6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="6 9 12 15 18 9"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="9 6 15 12 9 18"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="6 15 12 9 18 15"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><circle cx="12" cy="12" r="9"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 16 14"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><path d="M9 6h6v12H9z"/><rect x="3" y="3" width="6" height="6"/><rect x="15" y="3" width="6" height="6"/><rect x="3" y="15" width="6" height="6"/><rect x="15" y="15" width="6" height="6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><rect x="3" y="3" width="18" height="18"/><line x1="9" y1="3" x2="9" y2="21"/><line x1="15" y1="3" x2="15" y2="21"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><rect x="8" y="8" width="13" height="13"/><path d="M16 8V4H4v13h4"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><rect x="6" y="6" width="12" height="12"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="2" x2="9" y2="6"/><line x1="15" y1="2" x2="15" y2="6"/><line x1="9" y1="18" x2="9" y2="22"/><line x1="15" y1="18" x2="15" y2="22"/><line x1="2" y1="9" x2="6" y2="9"/><line x1="2" y1="15" x2="6" y2="15"/><line x1="18" y1="9" x2="22" y2="9"/><line x1="18" y1="15" x2="22" y2="15"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#0C0C0D" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><line x1="12" y1="2" x2="12" y2="22"/><path d="M17 6H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><path d="M12 3v12"/><polyline points="7 10 12 15 17 10"/><line x1="3" y1="21" x2="21" y2="21"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><path d="M4 20h4l10-10-4-4L4 16v4z"/><path d="M14 6l4 4"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><path d="M17.5 14v3.5H21a2 2 0 0 1 0 4h-3.5V21a2 2 0 0 1-4 0v-3.5H14a2 2 0 0 1 0-4h3.5z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><polyline points="14 4 20 4 20 10"/><line x1="20" y1="4" x2="11" y2="13"/><path d="M20 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#D1D3DB" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/></svg>