@octans/ui 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 (283) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -0
  3. package/bin/octans-icons.mjs +208 -0
  4. package/dist/components/ActionList/ActionList.vue.d.ts +77 -0
  5. package/dist/components/ActionList/ActionListButton.vue.d.ts +85 -0
  6. package/dist/components/ActionList/ActionListMenu.vue.d.ts +18 -0
  7. package/dist/components/ActionList/index.d.ts +1 -0
  8. package/dist/components/AppFrame/AppFrame.vue.d.ts +26 -0
  9. package/dist/components/AppFrame/context.d.ts +40 -0
  10. package/dist/components/AppFrame/index.d.ts +3 -0
  11. package/dist/components/AppFrame/types.d.ts +52 -0
  12. package/dist/components/Badge/Badge.vue.d.ts +125 -0
  13. package/dist/components/Badge/index.d.ts +1 -0
  14. package/dist/components/Banner/Banner.vue.d.ts +239 -0
  15. package/dist/components/Banner/index.d.ts +1 -0
  16. package/dist/components/Button/Button.vue.d.ts +284 -0
  17. package/dist/components/Button/ButtonGroup.vue.d.ts +44 -0
  18. package/dist/components/Button/ButtonGroupItem.vue.d.ts +5 -0
  19. package/dist/components/Button/index.d.ts +3 -0
  20. package/dist/components/Calendar/Calendar.vue.d.ts +15 -0
  21. package/dist/components/Calendar/index.d.ts +2 -0
  22. package/dist/components/Calendar/types.d.ts +39 -0
  23. package/dist/components/CalendarHeatmap/CalendarHeatmap.vue.d.ts +21 -0
  24. package/dist/components/CalendarHeatmap/index.d.ts +2 -0
  25. package/dist/components/CalendarHeatmap/types.d.ts +168 -0
  26. package/dist/components/Caption/Caption.vue.d.ts +5 -0
  27. package/dist/components/Caption/index.d.ts +1 -0
  28. package/dist/components/Card/Card.vue.d.ts +82 -0
  29. package/dist/components/Card/CardSection.vue.d.ts +89 -0
  30. package/dist/components/Card/index.d.ts +2 -0
  31. package/dist/components/Card/utils.d.ts +4 -0
  32. package/dist/components/Checkbox/Checkbox.vue.d.ts +171 -0
  33. package/dist/components/Checkbox/CheckboxControl.vue.d.ts +59 -0
  34. package/dist/components/Checkbox/index.d.ts +2 -0
  35. package/dist/components/Choice/Choice.vue.d.ts +102 -0
  36. package/dist/components/Choice/index.d.ts +1 -0
  37. package/dist/components/ChoiceList/ChoiceList.vue.d.ts +199 -0
  38. package/dist/components/ChoiceList/index.d.ts +2 -0
  39. package/dist/components/ChoiceList/types.d.ts +31 -0
  40. package/dist/components/ColorPicker/ColorPicker.vue.d.ts +18 -0
  41. package/dist/components/ColorPicker/index.d.ts +2 -0
  42. package/dist/components/ColorPicker/types.d.ts +62 -0
  43. package/dist/components/ColorSelector/ColorSelector.vue.d.ts +34 -0
  44. package/dist/components/ColorSelector/index.d.ts +2 -0
  45. package/dist/components/ColorSelector/types.d.ts +143 -0
  46. package/dist/components/DataTable/BulkActions.vue.d.ts +282 -0
  47. package/dist/components/DataTable/DataTable.vue.d.ts +40 -0
  48. package/dist/components/DataTable/DataTableFooter.vue.d.ts +22 -0
  49. package/dist/components/DataTable/index.d.ts +2 -0
  50. package/dist/components/DataTable/types.d.ts +249 -0
  51. package/dist/components/DatePicker/DatePicker.vue.d.ts +17 -0
  52. package/dist/components/DatePicker/index.d.ts +4 -0
  53. package/dist/components/DatePicker/types.d.ts +57 -0
  54. package/dist/components/Divider/Divider.vue.d.ts +20 -0
  55. package/dist/components/Divider/index.d.ts +2 -0
  56. package/dist/components/Divider/types.d.ts +76 -0
  57. package/dist/components/EventDelegator/EventDelegator.vue.d.ts +18 -0
  58. package/dist/components/EventDelegator/index.d.ts +1 -0
  59. package/dist/components/EventDelegator/utils.d.ts +25 -0
  60. package/dist/components/FileInput/DropZone.vue.d.ts +67 -0
  61. package/dist/components/FileInput/FileInput.vue.d.ts +422 -0
  62. package/dist/components/FileInput/ItemList.vue.d.ts +109 -0
  63. package/dist/components/FileInput/index.d.ts +1 -0
  64. package/dist/components/FileInput/utils.d.ts +15 -0
  65. package/dist/components/Filters/FilterActions.vue.d.ts +236 -0
  66. package/dist/components/Filters/FilterItem.vue.d.ts +813 -0
  67. package/dist/components/Filters/Filters.vue.d.ts +1627 -0
  68. package/dist/components/Filters/index.d.ts +1 -0
  69. package/dist/components/Filters/utils.d.ts +1 -0
  70. package/dist/components/FooterHelp/FooterHelp.vue.d.ts +16 -0
  71. package/dist/components/FooterHelp/index.d.ts +1 -0
  72. package/dist/components/FormLayout/FormLayout.vue.d.ts +5 -0
  73. package/dist/components/FormLayout/FormLayoutGroup.vue.d.ts +17 -0
  74. package/dist/components/FormLayout/index.d.ts +2 -0
  75. package/dist/components/Formatter/Formatter.vue.d.ts +42 -0
  76. package/dist/components/Formatter/index.d.ts +1 -0
  77. package/dist/components/GlobalNav/GlobalNav.vue.d.ts +33 -0
  78. package/dist/components/GlobalNav/index.d.ts +2 -0
  79. package/dist/components/GlobalNav/types.d.ts +64 -0
  80. package/dist/components/GradientPicker/GradientPicker.vue.d.ts +20 -0
  81. package/dist/components/GradientPicker/index.d.ts +2 -0
  82. package/dist/components/GradientPicker/types.d.ts +74 -0
  83. package/dist/components/Heading/Heading.vue.d.ts +18 -0
  84. package/dist/components/Heading/index.d.ts +1 -0
  85. package/dist/components/Icon/Icon.vue.d.ts +112 -0
  86. package/dist/components/Icon/iconBundle.d.ts +1 -0
  87. package/dist/components/Icon/index.d.ts +1 -0
  88. package/dist/components/InlineError/InlineError.vue.d.ts +6 -0
  89. package/dist/components/InlineError/index.d.ts +1 -0
  90. package/dist/components/Labelled/Labelled.vue.d.ts +110 -0
  91. package/dist/components/Labelled/index.d.ts +1 -0
  92. package/dist/components/Layout/Layout.vue.d.ts +13 -0
  93. package/dist/components/Layout/LayoutSection.vue.d.ts +16 -0
  94. package/dist/components/Layout/LayoutSectionAnnotated.vue.d.ts +34 -0
  95. package/dist/components/Layout/index.d.ts +3 -0
  96. package/dist/components/LineClamper/LineClamper.vue.d.ts +16 -0
  97. package/dist/components/LineClamper/index.d.ts +2 -0
  98. package/dist/components/LineClamper/types.d.ts +7 -0
  99. package/dist/components/Link/Link.vue.d.ts +19 -0
  100. package/dist/components/Link/index.d.ts +1 -0
  101. package/dist/components/List/List.vue.d.ts +15 -0
  102. package/dist/components/List/ListItem.vue.d.ts +16 -0
  103. package/dist/components/List/index.d.ts +3 -0
  104. package/dist/components/List/types.d.ts +51 -0
  105. package/dist/components/LoaderOverlay/LoaderOverlay.vue.d.ts +18 -0
  106. package/dist/components/LoaderOverlay/host.d.ts +6 -0
  107. package/dist/components/LoaderOverlay/index.d.ts +26 -0
  108. package/dist/components/LoaderOverlay/store.d.ts +7 -0
  109. package/dist/components/LoaderOverlay/types.d.ts +24 -0
  110. package/dist/components/LoadingBar/LoadingBar.vue.d.ts +7 -0
  111. package/dist/components/LoadingBar/host.d.ts +6 -0
  112. package/dist/components/LoadingBar/index.d.ts +28 -0
  113. package/dist/components/LoadingBar/store.d.ts +6 -0
  114. package/dist/components/LoadingBar/types.d.ts +16 -0
  115. package/dist/components/MaybeMountingPortal/MaybeMountingPortal.vue.d.ts +53 -0
  116. package/dist/components/MaybeMountingPortal/index.d.ts +1 -0
  117. package/dist/components/MaybeRouterLink/MaybeRouterLink.vue.d.ts +34 -0
  118. package/dist/components/MaybeRouterLink/index.d.ts +2 -0
  119. package/dist/components/MaybeRouterLink/types.d.ts +49 -0
  120. package/dist/components/Modal/Modal.vue.d.ts +28 -0
  121. package/dist/components/Modal/ModalBackdrop.vue.d.ts +12 -0
  122. package/dist/components/Modal/ModalHost.vue.d.ts +3 -0
  123. package/dist/components/Modal/ModalStackItem.vue.d.ts +14 -0
  124. package/dist/components/Modal/api/AlertModal.vue.d.ts +10 -0
  125. package/dist/components/Modal/api/Base.d.ts +12 -0
  126. package/dist/components/Modal/api/ConfirmModal.vue.d.ts +10 -0
  127. package/dist/components/Modal/api/GenericModal.vue.d.ts +10 -0
  128. package/dist/components/Modal/api/PromptModal.vue.d.ts +10 -0
  129. package/dist/components/Modal/api/types.d.ts +110 -0
  130. package/dist/components/Modal/host.d.ts +2 -0
  131. package/dist/components/Modal/index.d.ts +10 -0
  132. package/dist/components/Modal/manager.d.ts +80 -0
  133. package/dist/components/Modal/types.d.ts +49 -0
  134. package/dist/components/NavField/NavField.vue.d.ts +223 -0
  135. package/dist/components/NavField/index.d.ts +1 -0
  136. package/dist/components/Navigation/Navigation.vue.d.ts +47 -0
  137. package/dist/components/Navigation/components/Item.vue.d.ts +10 -0
  138. package/dist/components/Navigation/components/Section.vue.d.ts +13 -0
  139. package/dist/components/Navigation/index.d.ts +2 -0
  140. package/dist/components/Navigation/types.d.ts +117 -0
  141. package/dist/components/OtpInput/OtpInput.vue.d.ts +21 -0
  142. package/dist/components/OtpInput/index.d.ts +2 -0
  143. package/dist/components/OtpInput/types.d.ts +87 -0
  144. package/dist/components/Page/Page.vue.d.ts +34 -0
  145. package/dist/components/Page/index.d.ts +2 -0
  146. package/dist/components/Page/types.d.ts +75 -0
  147. package/dist/components/PageActions/PageActions.vue.d.ts +6 -0
  148. package/dist/components/PageActions/index.d.ts +2 -0
  149. package/dist/components/PageActions/types.d.ts +17 -0
  150. package/dist/components/Pagination/Pagination.vue.d.ts +22 -0
  151. package/dist/components/Pagination/index.d.ts +1 -0
  152. package/dist/components/Popper/Popper.vue.d.ts +45 -0
  153. package/dist/components/Popper/index.d.ts +2 -0
  154. package/dist/components/Popper/types.d.ts +29 -0
  155. package/dist/components/PreventAutoComplete/PreventAutoComplete.vue.d.ts +24 -0
  156. package/dist/components/PreventAutoComplete/index.d.ts +1 -0
  157. package/dist/components/ProgressBar/ProgressBar.vue.d.ts +48 -0
  158. package/dist/components/ProgressBar/index.d.ts +2 -0
  159. package/dist/components/RadioButton/RadioButton.vue.d.ts +143 -0
  160. package/dist/components/RadioButton/RadioButtonControl.vue.d.ts +50 -0
  161. package/dist/components/RadioButton/index.d.ts +2 -0
  162. package/dist/components/RangeSlider/RangeSlider.vue.d.ts +303 -0
  163. package/dist/components/RangeSlider/index.d.ts +1 -0
  164. package/dist/components/Rating/Rating.vue.d.ts +20 -0
  165. package/dist/components/Rating/index.d.ts +2 -0
  166. package/dist/components/Rating/types.d.ts +78 -0
  167. package/dist/components/ResourceList/ResourceItem.vue.d.ts +17 -0
  168. package/dist/components/ResourceList/ResourceList.vue.d.ts +19 -0
  169. package/dist/components/ResourceList/index.d.ts +3 -0
  170. package/dist/components/ResourceList/types.d.ts +19 -0
  171. package/dist/components/SaveBar/SaveBar.vue.d.ts +15 -0
  172. package/dist/components/SaveBar/index.d.ts +4 -0
  173. package/dist/components/SaveBar/store.d.ts +56 -0
  174. package/dist/components/SaveBar/types.d.ts +42 -0
  175. package/dist/components/SaveBarController/SaveBarController.vue.d.ts +40 -0
  176. package/dist/components/SaveBarController/index.d.ts +1 -0
  177. package/dist/components/ScrollPane/ScrollPane.vue.d.ts +24 -0
  178. package/dist/components/ScrollPane/index.d.ts +2 -0
  179. package/dist/components/ScrollPane/types.d.ts +64 -0
  180. package/dist/components/SegmentedControl/SegmentedControl.vue.d.ts +39 -0
  181. package/dist/components/SegmentedControl/index.d.ts +2 -0
  182. package/dist/components/SegmentedControl/types.d.ts +119 -0
  183. package/dist/components/Select/Select.vue.d.ts +901 -0
  184. package/dist/components/Select/index.d.ts +3 -0
  185. package/dist/components/Sheet/Sheet.vue.d.ts +41 -0
  186. package/dist/components/Sheet/index.d.ts +2 -0
  187. package/dist/components/Sheet/manager.d.ts +34 -0
  188. package/dist/components/Sheet/types.d.ts +92 -0
  189. package/dist/components/SkeletonBodyText/SkeletonBodyText.vue.d.ts +17 -0
  190. package/dist/components/SkeletonBodyText/index.d.ts +1 -0
  191. package/dist/components/SkeletonCard/SkeletonCard.vue.d.ts +34 -0
  192. package/dist/components/SkeletonCard/index.d.ts +1 -0
  193. package/dist/components/SkeletonDisplayText/SkeletonDisplayText.vue.d.ts +17 -0
  194. package/dist/components/SkeletonDisplayText/index.d.ts +1 -0
  195. package/dist/components/Spinner/Spinner.vue.d.ts +52 -0
  196. package/dist/components/Spinner/index.d.ts +1 -0
  197. package/dist/components/Splitter/Splitter.vue.d.ts +60 -0
  198. package/dist/components/Splitter/index.d.ts +2 -0
  199. package/dist/components/Splitter/types.d.ts +177 -0
  200. package/dist/components/Stack/Stack.vue.d.ts +130 -0
  201. package/dist/components/Stack/StackItem.vue.d.ts +23 -0
  202. package/dist/components/Stack/index.d.ts +2 -0
  203. package/dist/components/StatGroup/Stat.vue.d.ts +16 -0
  204. package/dist/components/StatGroup/StatGroup.vue.d.ts +17 -0
  205. package/dist/components/StatGroup/index.d.ts +3 -0
  206. package/dist/components/StatGroup/types.d.ts +42 -0
  207. package/dist/components/Sticky/Sticky.vue.d.ts +27 -0
  208. package/dist/components/Sticky/index.d.ts +2 -0
  209. package/dist/components/Sticky/types.d.ts +24 -0
  210. package/dist/components/SyntaxHighlighter/SyntaxHighlighter.vue.d.ts +12 -0
  211. package/dist/components/SyntaxHighlighter/index.d.ts +2 -0
  212. package/dist/components/SyntaxHighlighter/types.d.ts +10 -0
  213. package/dist/components/Tabs/Tabs.vue.d.ts +23 -0
  214. package/dist/components/Tabs/index.d.ts +2 -0
  215. package/dist/components/Tabs/types.d.ts +19 -0
  216. package/dist/components/Tag/Tag.vue.d.ts +29 -0
  217. package/dist/components/Tag/index.d.ts +1 -0
  218. package/dist/components/TextContainer/TextContainer.vue.d.ts +13 -0
  219. package/dist/components/TextContainer/index.d.ts +1 -0
  220. package/dist/components/TextField/TextField.vue.d.ts +38 -0
  221. package/dist/components/TextField/index.d.ts +2 -0
  222. package/dist/components/TextField/types.d.ts +130 -0
  223. package/dist/components/TextStyle/TextStyle.vue.d.ts +15 -0
  224. package/dist/components/TextStyle/index.d.ts +1 -0
  225. package/dist/components/Thumbnail/Thumbnail.vue.d.ts +17 -0
  226. package/dist/components/Thumbnail/index.d.ts +2 -0
  227. package/dist/components/Thumbnail/types.d.ts +32 -0
  228. package/dist/components/TimePicker/TimePicker.vue.d.ts +25 -0
  229. package/dist/components/TimePicker/index.d.ts +2 -0
  230. package/dist/components/TimePicker/types.d.ts +90 -0
  231. package/dist/components/TimezonePicker/TimezonePicker.vue.d.ts +15 -0
  232. package/dist/components/TimezonePicker/index.d.ts +2 -0
  233. package/dist/components/TimezonePicker/types.d.ts +50 -0
  234. package/dist/components/TimezonePicker/zoneCountries.d.ts +2 -0
  235. package/dist/components/ToastManager/ProgressBar.vue.d.ts +8 -0
  236. package/dist/components/ToastManager/Toast.vue.d.ts +14 -0
  237. package/dist/components/ToastManager/ToastManager.vue.d.ts +19 -0
  238. package/dist/components/ToastManager/host.d.ts +14 -0
  239. package/dist/components/ToastManager/index.d.ts +24 -0
  240. package/dist/components/ToastManager/manager.d.ts +45 -0
  241. package/dist/components/ToastManager/types.d.ts +44 -0
  242. package/dist/components/ToggleSwitch/ToggleSwitch.vue.d.ts +35 -0
  243. package/dist/components/ToggleSwitch/index.d.ts +2 -0
  244. package/dist/components/ToggleSwitch/types.d.ts +84 -0
  245. package/dist/components/Tooltip/Tooltip.vue.d.ts +20 -0
  246. package/dist/components/Tooltip/index.d.ts +1 -0
  247. package/dist/components/UiProvider/UiProvider.vue.d.ts +16 -0
  248. package/dist/components/UiProvider/index.d.ts +2 -0
  249. package/dist/components/UiProvider/types.d.ts +2 -0
  250. package/dist/components/UiProvider/utils.d.ts +5 -0
  251. package/dist/components/UnstyledLink/UnstyledLink.vue.d.ts +5 -0
  252. package/dist/components/UnstyledLink/index.d.ts +1 -0
  253. package/dist/components/all.d.ts +92 -0
  254. package/dist/components/types.d.ts +74 -0
  255. package/dist/globalExtensions.d.ts +7 -0
  256. package/dist/i18n/en.json.d.ts +60 -0
  257. package/dist/lib.d.ts +67 -0
  258. package/dist/lib.umd.d.ts +1 -0
  259. package/dist/style.css +2 -0
  260. package/dist/test/setup.d.ts +1 -0
  261. package/dist/ui.js +20051 -0
  262. package/dist/ui.umd.js +10 -0
  263. package/dist/utils/autoHost.d.ts +27 -0
  264. package/dist/utils/color.d.ts +112 -0
  265. package/dist/utils/colorRamp.d.ts +51 -0
  266. package/dist/utils/createTheme.d.ts +52 -0
  267. package/dist/utils/customTheme.d.ts +73 -0
  268. package/dist/utils/date.d.ts +4 -0
  269. package/dist/utils/debounce.d.ts +3 -0
  270. package/dist/utils/deferredPromise.d.ts +6 -0
  271. package/dist/utils/format.d.ts +9 -0
  272. package/dist/utils/fuzzy.d.ts +33 -0
  273. package/dist/utils/gradient.d.ts +83 -0
  274. package/dist/utils/index.d.ts +31 -0
  275. package/dist/utils/loader.d.ts +1 -0
  276. package/dist/utils/positionPanel.d.ts +32 -0
  277. package/dist/utils/radix.d.ts +6 -0
  278. package/dist/utils/theme.d.ts +42 -0
  279. package/dist/utils/timezone.d.ts +66 -0
  280. package/dist/utils/tokens.d.ts +62 -0
  281. package/dist/utils/translate.d.ts +27 -0
  282. package/dist/zoneCountries-CWZGMHyp.js +353 -0
  283. package/package.json +120 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tarwin Stroh-Spijer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,226 @@
1
+ <img src="./octans-logo.svg" alt="" width="72" height="72" align="left" hspace="12" />
2
+
3
+ # Octans UI
4
+
5
+ A Vue 3 component library — friendly, accessible, themeable UI primitives and application
6
+ shell components.
7
+
8
+ <br clear="left" />
9
+
10
+ [octans.dev](https://octans.dev) — live Storybook docs ·
11
+ [github.com/tarwin/octans-ui](https://github.com/tarwin/octans-ui) ·
12
+ [Issues](https://github.com/tarwin/octans-ui/issues)
13
+
14
+ ## Install
15
+
16
+ ```sh
17
+ pnpm add @octans/ui
18
+ ```
19
+
20
+ `vue` is a peer dependency. `vue-router` is an optional peer — you only need it
21
+ if you use the components that render router links (`MaybeRouterLink`,
22
+ `UnstyledLink`, and anything that accepts a `to` prop).
23
+
24
+ ## Usage
25
+
26
+ ```ts
27
+ import { createApp } from 'vue'
28
+ import Octans from '@octans/ui'
29
+ import '@octans/ui/style.css'
30
+
31
+ import App from './App.vue'
32
+
33
+ createApp(App).use(Octans).mount('#app')
34
+ ```
35
+
36
+ Components can also be imported individually without installing the plugin:
37
+
38
+ ```vue
39
+ <script setup lang="ts">
40
+ import { Button, Card } from '@octans/ui'
41
+ </script>
42
+
43
+ <template>
44
+ <Card title="Hello">
45
+ <Button primary>Click me</Button>
46
+ </Card>
47
+ </template>
48
+ ```
49
+
50
+ Installing the plugin additionally registers the `$ui` and `$t` globals, which
51
+ give you the imperative APIs (`$ui.toast`, `$ui.confirm`, `$ui.format`, …) from
52
+ inside templates.
53
+
54
+ Most components that manage overlays expect a `<UiProvider>` at the root of your
55
+ app, so tooltips can share a single delay group:
56
+
57
+ ```vue
58
+ <template>
59
+ <UiProvider>
60
+ <RouterView />
61
+ </UiProvider>
62
+ </template>
63
+ ```
64
+
65
+ ## Translations
66
+
67
+ Every user-facing string resolves through a small built-in dictionary. English
68
+ ships with the library and is always the fallback, so a missing key degrades to
69
+ readable English rather than a raw dotted key.
70
+
71
+ ```ts
72
+ import { addTranslations, setTranslationLocale } from '@octans/ui'
73
+
74
+ addTranslations('fr', {
75
+ 'ui.modal.close': 'Fermer',
76
+ 'ui.modal.cancel': 'Annuler'
77
+ })
78
+ setTranslationLocale('fr')
79
+ ```
80
+
81
+ Or supply them when installing the plugin:
82
+
83
+ ```ts
84
+ app.use(Octans, {
85
+ locale: 'fr',
86
+ translations: { fr: { 'ui.modal.close': 'Fermer' } }
87
+ })
88
+ ```
89
+
90
+ Strings support `{placeholder}` interpolation. Unknown placeholders are left
91
+ in place rather than rendering `undefined`, so gaps are visible.
92
+
93
+ ## Icons
94
+
95
+ Icons resolve through [Iconify](https://iconify.design). **Every icon the
96
+ library uses internally is pre-bundled**, so components render offline with no
97
+ network request and no icon font to install.
98
+
99
+ Names you pass yourself resolve through `api.iconify.design` at runtime. That
100
+ needs no build step, but it is a round trip on first use and renders nothing at
101
+ all offline. To bundle exactly the icons your app uses, run this before a build
102
+ and commit the result:
103
+
104
+ ```sh
105
+ npx octans-icons # scans ./src, writes src/octansIcons.ts
106
+ ```
107
+
108
+ ```ts
109
+ import './octansIcons' // once, at startup
110
+ ```
111
+
112
+ It finds Iconify names in your source, fetches only those, and generates a file
113
+ that registers them. Re-run it when you add an icon; `npx octans-icons --help`
114
+ lists the options. Names your code builds at runtime (`` `mdi:${name}` ``) can't
115
+ be seen by a source scan and keep resolving through the API.
116
+
117
+ To bundle a whole collection instead — simpler, but `@iconify-json/lucide` is
118
+ roughly 1.5 MB against a typical app's few kB of actual icons:
119
+
120
+ ```ts
121
+ import { addCollection } from '@octans/ui'
122
+ import icons from '@iconify-json/lucide/icons.json'
123
+
124
+ addCollection(icons)
125
+ ```
126
+
127
+ Font Awesome class strings (`fa fa-plus`) are still accepted for compatibility,
128
+ but the library no longer uses or ships Font Awesome — load it yourself if you
129
+ pass those names.
130
+
131
+ ## Theming
132
+
133
+ Colours, radii and shadows are CSS custom properties, so themes swap at runtime:
134
+
135
+ ```ts
136
+ import { setTheme, persistTheme } from '@octans/ui'
137
+
138
+ setTheme('dark') // 'light' | 'dark' | 'system'
139
+ persistTheme() // optional: remember the choice across reloads
140
+ ```
141
+
142
+ To rebrand, generate a theme from seed colours — every ramp and semantic token
143
+ follows, dark mode included:
144
+
145
+ ```ts
146
+ import { createTheme, applyCustomTheme } from '@octans/ui'
147
+
148
+ applyCustomTheme(createTheme({ name: 'Ocean', primary: '#0f9d8f' }))
149
+ ```
150
+
151
+ Or override any semantic token directly:
152
+
153
+ ```css
154
+ :root {
155
+ --octans-primary: #0f9d8f;
156
+ --octans-radius-field: 0; /* square controls */
157
+ }
158
+ ```
159
+
160
+ See the **Design Tokens** and **Theme Builder** pages in Storybook for the full
161
+ token list and an interactive editor.
162
+
163
+ ## Development
164
+
165
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full workflow — the short
166
+ version:
167
+
168
+ ```sh
169
+ pnpm install
170
+ pnpm dev # Storybook on :6006
171
+ ```
172
+
173
+ | Script | Does |
174
+ | ----------------- | ------------------------------------------------ |
175
+ | `pnpm dev` | Storybook dev server |
176
+ | `pnpm build-lib` | Build the ES + UMD bundles and type declarations |
177
+ | `pnpm type-check` | `vue-tsc --noEmit` |
178
+ | `pnpm lint` | ESLint |
179
+ | `pnpm format` | Prettier |
180
+ | `pnpm verify` | lint + type-check + build |
181
+
182
+ ## Conventions
183
+
184
+ ### Import public components by directory
185
+
186
+ Especially when one public component imports another.
187
+
188
+ ```ts
189
+ // ✅ Good
190
+ import { Button } from '@/components/Button'
191
+
192
+ // ❌ Unnecessarily longer
193
+ import { Button } from '@/components/Button/Button.vue'
194
+
195
+ // ❌ We can't easily search for '@/components/' to find references
196
+ import { Button } from '../Button'
197
+
198
+ // ❌ Creates a dependency on ALL components
199
+ import { Button } from '@/components/index.ts'
200
+ ```
201
+
202
+ ### Order SFC sections consistently
203
+
204
+ `<script>`, then `<template>`, then `<style>` — per the
205
+ [official Vue recommendation](https://vuejs.org/style-guide/rules-recommended.html#single-file-component-top-level-element-order).
206
+
207
+ ### Name component types predictably
208
+
209
+ Each component exports an interface defining its public props, named
210
+ `<Component>Props`. Supporting types start with the component name and end in
211
+ `Type`:
212
+
213
+ ```ts
214
+ export interface SelectProps {
215
+ options: SelectOptionType[]
216
+ }
217
+
218
+ export interface SelectOptionType {
219
+ value: string
220
+ label: string
221
+ }
222
+ ```
223
+
224
+ ## License
225
+
226
+ [MIT](./LICENSE)
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env node
2
+ //
3
+ // octans-icons — bundle the Iconify icons your app actually uses.
4
+ //
5
+ // @octans/ui ships only the icons the library itself renders. Anything else you
6
+ // pass to `<Icon icon="...">` is fetched from api.iconify.design on first use.
7
+ // That is a fine default — you get all 200k+ icons with no build step — but it
8
+ // means a network round trip per collection, nothing at all offline, and a
9
+ // third-party dependency at runtime.
10
+ //
11
+ // This scans your source for Iconify names, fetches just those, and writes a
12
+ // file you import once at startup. Run it before a build; commit the output.
13
+ //
14
+ // npx octans-icons # scans ./src, writes src/octansIcons.ts
15
+ // npx octans-icons app --out app/icons.ts
16
+ // npx octans-icons --dry-run # list what it finds, write nothing
17
+ //
18
+ // Deliberately standalone — no imports from the rest of the package, so it
19
+ // keeps working regardless of what the library's own build is doing.
20
+
21
+ import { readFile, readdir, writeFile } from 'node:fs/promises'
22
+ import { dirname, extname, join, relative, resolve } from 'node:path'
23
+
24
+ const HELP = `octans-icons — bundle the Iconify icons your app uses
25
+
26
+ Usage
27
+ npx octans-icons [dir...] [options]
28
+
29
+ Options
30
+ --out <file> Where to write the bundle. Default: <first dir>/octansIcons.ts
31
+ A .js extension emits JavaScript instead of TypeScript.
32
+ --dry-run Print the icons found and exit without writing.
33
+ --quiet Only print errors.
34
+ -h, --help Show this.
35
+
36
+ Then import it once, before anything renders:
37
+
38
+ import './octansIcons'
39
+
40
+ Re-run it whenever you add an icon. Names built at runtime (\`\\\`mdi:\${name}\\\`\`)
41
+ can't be seen by a source scan — those keep resolving through the API, which
42
+ still works. Pass them explicitly by putting the literal names in an array.
43
+ `
44
+
45
+ const args = process.argv.slice(2)
46
+ if (args.includes('-h') || args.includes('--help')) {
47
+ console.log(HELP)
48
+ process.exit(0)
49
+ }
50
+
51
+ const takeFlag = (name) => {
52
+ const index = args.indexOf(name)
53
+ if (index === -1) return undefined
54
+ const value = args[index + 1]
55
+ if (value === undefined || value.startsWith('-')) {
56
+ console.error(`octans-icons: ${name} needs a value`)
57
+ process.exit(1)
58
+ }
59
+ args.splice(index, 2)
60
+ return value
61
+ }
62
+
63
+ const outFlag = takeFlag('--out')
64
+ const dryRun = args.includes('--dry-run')
65
+ const quiet = args.includes('--quiet')
66
+ const dirs = args.filter((arg) => !arg.startsWith('-'))
67
+ const roots = dirs.length ? dirs : ['src']
68
+ const outFile = resolve(outFlag ?? join(roots[0], 'octansIcons.ts'))
69
+
70
+ const say = (message) => {
71
+ if (!quiet) console.log(message)
72
+ }
73
+
74
+ const SCANNABLE = /\.(vue|ts|tsx|js|jsx|mjs|cjs|svelte|astro|html)$/
75
+ const IGNORED_DIRS = new Set(['node_modules', 'dist', 'build', 'coverage'])
76
+
77
+ const walk = async (dir) => {
78
+ const files = []
79
+ let entries
80
+ try {
81
+ entries = await readdir(dir, { withFileTypes: true })
82
+ } catch {
83
+ console.error(`octans-icons: cannot read ${dir}`)
84
+ process.exit(1)
85
+ }
86
+ for (const entry of entries) {
87
+ if (IGNORED_DIRS.has(entry.name) || entry.name.startsWith('.')) continue
88
+ const path = join(dir, entry.name)
89
+ if (entry.isDirectory()) files.push(...(await walk(path)))
90
+ else if (SCANNABLE.test(entry.name)) files.push(path)
91
+ }
92
+ return files
93
+ }
94
+
95
+ // A name in a comment is documentation, not usage. Line-level on purpose: it
96
+ // drops whole comment lines rather than trying to parse a trailing `//` out of
97
+ // a line that may well contain one inside a string.
98
+ const isCommentLine = (line) => {
99
+ const trimmed = line.trimStart()
100
+ return ['*', '//', '/*', '<!--'].some((marker) => trimmed.startsWith(marker))
101
+ }
102
+
103
+ // Any quoted `prefix:name` is a candidate. `prefix` alone is far too loose —
104
+ // "height:100vh" and "grid:1 / 3" have the same shape — so candidates are kept
105
+ // only if the prefix is a real Iconify collection, which the API can tell us.
106
+ const CANDIDATE =
107
+ /["'`](?:not:)?([a-z0-9]+(?:-[a-z0-9]+)*):([a-z0-9]+(?:-[a-z0-9]+)*)["'`]/g
108
+
109
+ const fetchJson = async (url) => {
110
+ let response
111
+ try {
112
+ response = await fetch(url)
113
+ } catch (error) {
114
+ console.error(
115
+ `octans-icons: could not reach api.iconify.design — ${error.message}`
116
+ )
117
+ process.exit(1)
118
+ }
119
+ if (!response.ok) {
120
+ console.error(
121
+ `octans-icons: ${url} — ${response.status} ${response.statusText}`
122
+ )
123
+ process.exit(1)
124
+ }
125
+ return response.json()
126
+ }
127
+
128
+ const files = (await Promise.all(roots.map((dir) => walk(dir)))).flat()
129
+ if (!files.length) {
130
+ console.error(`octans-icons: no source files under ${roots.join(', ')}`)
131
+ process.exit(1)
132
+ }
133
+
134
+ const candidates = new Map()
135
+ for (const file of files) {
136
+ if (resolve(file) === outFile) continue
137
+ const source = await readFile(file, 'utf8')
138
+ for (const line of source.split('\n')) {
139
+ if (isCommentLine(line)) continue
140
+ for (const [, prefix, icon] of line.matchAll(CANDIDATE)) {
141
+ if (!candidates.has(prefix)) candidates.set(prefix, new Set())
142
+ candidates.get(prefix).add(icon)
143
+ }
144
+ }
145
+ }
146
+
147
+ say(`Scanned ${files.length} files in ${roots.join(', ')}`)
148
+
149
+ const collectionList = await fetchJson('https://api.iconify.design/collections')
150
+ const known = [...candidates].filter(([prefix]) => prefix in collectionList)
151
+
152
+ if (!known.length) {
153
+ console.error('octans-icons: no Iconify names found — nothing to bundle.')
154
+ process.exit(1)
155
+ }
156
+
157
+ const collections = []
158
+ const skipped = []
159
+ for (const [prefix, icons] of known.sort()) {
160
+ const names = [...icons].sort()
161
+ const data = await fetchJson(
162
+ `https://api.iconify.design/${prefix}.json?icons=${names.join(',')}`
163
+ )
164
+ // A miss is not fatal here: the candidate pattern is greedy by design, so an
165
+ // unknown name is as likely to be a false positive as a typo. Those keep
166
+ // working through the API, so warn and carry on rather than break a build.
167
+ for (const name of names) {
168
+ if (!data.icons?.[name]) skipped.push(`${prefix}:${name}`)
169
+ }
170
+ if (data.icons && Object.keys(data.icons).length) {
171
+ collections.push(data)
172
+ say(` ${prefix}: ${Object.keys(data.icons).sort().join(', ')}`)
173
+ }
174
+ }
175
+
176
+ const total = collections.reduce((n, c) => n + Object.keys(c.icons).length, 0)
177
+ if (skipped.length) {
178
+ console.warn(
179
+ `\noctans-icons: not in Iconify, left to resolve at runtime — ${skipped.join(', ')}`
180
+ )
181
+ }
182
+
183
+ if (dryRun) {
184
+ say(`\n${total} icons found. Nothing written (--dry-run).`)
185
+ process.exit(0)
186
+ }
187
+
188
+ const isTs = extname(outFile) === '.ts'
189
+ const contents = `// GENERATED by \`npx octans-icons\` — do not edit by hand.
190
+ //
191
+ // Iconify data for every icon name found in this project's source, so they
192
+ // render instantly and offline instead of being fetched from the Iconify API.
193
+ // Import this once at startup, before anything renders.
194
+ //
195
+ // Re-run \`npx octans-icons\` after adding an icon.
196
+ import { addCollection } from '@octans/ui'
197
+
198
+ const collections = ${JSON.stringify(collections, null, 2)}
199
+
200
+ collections.forEach((collection) => addCollection(collection${isTs ? ' as any' : ''}))
201
+ `
202
+
203
+ await writeFile(outFile, contents)
204
+ say(
205
+ `\nWrote ${relative(process.cwd(), outFile)} — ${total} icons in ` +
206
+ `${collections.length} collection(s).\n\nImport it once at startup:\n` +
207
+ ` import './${relative(dirname(outFile), outFile).replace(/\.(ts|js)$/, '')}'`
208
+ )
@@ -0,0 +1,77 @@
1
+ import { PopperPlacementType } from '../Popper';
2
+ import { ActionTooltipPositionType } from '../types';
3
+ export interface ActionListProps {
4
+ /**
5
+ * A single list of actions to render.
6
+ */
7
+ items?: ActionListItemType[];
8
+ /**
9
+ * Groups of actions to render.
10
+ */
11
+ sections?: ActionListSectionType[];
12
+ placement?: PopperPlacementType;
13
+ disabled?: boolean;
14
+ /**
15
+ * Custom z-index for the popper.
16
+ */
17
+ zIndex?: number;
18
+ /**
19
+ * Open sub-menus on hover instead of click. Propagates to all nested levels.
20
+ */
21
+ autoOpen?: boolean;
22
+ /**
23
+ * Internal: makes this list's own trigger open on hover. Set by the parent
24
+ * menu when `autoOpen` is enabled; not meant to be set directly.
25
+ */
26
+ hoverTrigger?: boolean;
27
+ }
28
+ export interface ActionListItemType {
29
+ label: string;
30
+ icon?: string | null;
31
+ /**
32
+ * Secondary text shown beneath the label.
33
+ */
34
+ helpText?: string;
35
+ disabled?: boolean;
36
+ url?: string;
37
+ external?: boolean;
38
+ /**
39
+ * Tooltip to show when hovering the item.
40
+ */
41
+ tooltip?: string;
42
+ /**
43
+ * Tooltip position, "top", "bottom", "right" or "left".
44
+ */
45
+ tooltipPosition?: ActionTooltipPositionType;
46
+ onAction?(): void;
47
+ items?: ActionListItemType[];
48
+ sections?: ActionListSectionType[];
49
+ }
50
+ export interface ActionListSectionType {
51
+ items: ActionListItemType[];
52
+ title?: string;
53
+ }
54
+ declare var __VLS_19: {};
55
+ type __VLS_Slots = {} & {
56
+ default?: (props: typeof __VLS_19) => any;
57
+ };
58
+ declare const __VLS_base: import('vue').DefineComponent<ActionListProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
59
+ show: () => any;
60
+ hide: () => any;
61
+ close: () => any;
62
+ }, string, import('vue').PublicProps, Readonly<ActionListProps> & Readonly<{
63
+ onShow?: (() => any) | undefined;
64
+ onHide?: (() => any) | undefined;
65
+ onClose?: (() => any) | undefined;
66
+ }>, {
67
+ placement: PopperPlacementType;
68
+ items: ActionListItemType[];
69
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
70
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
71
+ declare const _default: typeof __VLS_export;
72
+ export default _default;
73
+ type __VLS_WithSlots<T, S> = T & {
74
+ new (): {
75
+ $slots: S;
76
+ };
77
+ };
@@ -0,0 +1,85 @@
1
+ import { PropType, VNode } from 'vue';
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
4
+ declare const __VLS_export: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
5
+ label: {
6
+ type: StringConstructor;
7
+ };
8
+ helpText: {
9
+ type: StringConstructor;
10
+ };
11
+ disabled: {
12
+ type: BooleanConstructor;
13
+ default: boolean;
14
+ };
15
+ /**
16
+ * Tooltip to show when hovering the button.
17
+ */
18
+ tooltip: {
19
+ type: StringConstructor;
20
+ };
21
+ /**
22
+ * Tooltip position, "top", "bottom", "right" or "left".
23
+ */
24
+ tooltipPosition: {
25
+ type: StringConstructor;
26
+ default: string;
27
+ };
28
+ dropdown: {
29
+ type: BooleanConstructor;
30
+ default: boolean;
31
+ };
32
+ url: {
33
+ type: StringConstructor;
34
+ };
35
+ external: {
36
+ type: BooleanConstructor;
37
+ };
38
+ icon: {
39
+ type: PropType<string | null>;
40
+ };
41
+ }>, () => VNode<import('vue').RendererNode, import('vue').RendererElement, {
42
+ [key: string]: any;
43
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
44
+ label: {
45
+ type: StringConstructor;
46
+ };
47
+ helpText: {
48
+ type: StringConstructor;
49
+ };
50
+ disabled: {
51
+ type: BooleanConstructor;
52
+ default: boolean;
53
+ };
54
+ /**
55
+ * Tooltip to show when hovering the button.
56
+ */
57
+ tooltip: {
58
+ type: StringConstructor;
59
+ };
60
+ /**
61
+ * Tooltip position, "top", "bottom", "right" or "left".
62
+ */
63
+ tooltipPosition: {
64
+ type: StringConstructor;
65
+ default: string;
66
+ };
67
+ dropdown: {
68
+ type: BooleanConstructor;
69
+ default: boolean;
70
+ };
71
+ url: {
72
+ type: StringConstructor;
73
+ };
74
+ external: {
75
+ type: BooleanConstructor;
76
+ };
77
+ icon: {
78
+ type: PropType<string | null>;
79
+ };
80
+ }>> & Readonly<{}>, {
81
+ disabled: boolean;
82
+ tooltipPosition: string;
83
+ external: boolean;
84
+ dropdown: boolean;
85
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,18 @@
1
+ import { ActionListItemType, ActionListSectionType } from './ActionList.vue';
2
+ export interface ActionListMenuProps {
3
+ items?: ActionListItemType[];
4
+ sections?: ActionListSectionType[];
5
+ /**
6
+ * Open sub-menus on hover instead of click. Propagates to nested levels.
7
+ */
8
+ autoOpen?: boolean;
9
+ }
10
+ declare const __VLS_export: import('vue').DefineComponent<ActionListMenuProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
11
+ close: () => any;
12
+ }, string, import('vue').PublicProps, Readonly<ActionListMenuProps> & Readonly<{
13
+ onClose?: (() => any) | undefined;
14
+ }>, {
15
+ items: ActionListItemType[];
16
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
17
+ declare const _default: typeof __VLS_export;
18
+ export default _default;
@@ -0,0 +1 @@
1
+ export { default as ActionList, type ActionListProps, type ActionListItemType, type ActionListSectionType } from './ActionList.vue';
@@ -0,0 +1,26 @@
1
+ import { AppFrameProps } from './types';
2
+ declare var __VLS_8: {}, __VLS_10: {}, __VLS_38: {}, __VLS_40: {};
3
+ type __VLS_Slots = {} & {
4
+ sidebar?: (props: typeof __VLS_8) => any;
5
+ } & {
6
+ topbar?: (props: typeof __VLS_10) => any;
7
+ } & {
8
+ default?: (props: typeof __VLS_38) => any;
9
+ } & {
10
+ footer?: (props: typeof __VLS_40) => any;
11
+ };
12
+ declare const __VLS_base: import('vue').DefineComponent<AppFrameProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<AppFrameProps> & Readonly<{}>, {
13
+ loading: boolean;
14
+ layout: import('./types').AppFrameLayoutType;
15
+ layoutMode: import('../GlobalNav').GlobalNavLayoutModeType;
16
+ sidebarMin: boolean;
17
+ sidebarCollapse: import('./types').AppFrameSidebarCollapseType;
18
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
19
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
20
+ declare const _default: typeof __VLS_export;
21
+ export default _default;
22
+ type __VLS_WithSlots<T, S> = T & {
23
+ new (): {
24
+ $slots: S;
25
+ };
26
+ };