@birdycom/omniaui-vue 0.11.0 → 0.11.1

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 (178) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +49 -49
  3. package/dist/omniaui-vue.js.map +1 -1
  4. package/package.json +69 -69
  5. package/src/blocks/OcBlockAboutTimeline.vue +44 -44
  6. package/src/blocks/OcBlockAppHeader.vue +36 -36
  7. package/src/blocks/OcBlockAppShell.vue +29 -29
  8. package/src/blocks/OcBlockAuth.vue +24 -24
  9. package/src/blocks/OcBlockAuthSplit.vue +47 -47
  10. package/src/blocks/OcBlockContactGrid.vue +53 -53
  11. package/src/blocks/OcBlockCta.vue +12 -12
  12. package/src/blocks/OcBlockDataTable.vue +27 -27
  13. package/src/blocks/OcBlockFaq.vue +49 -49
  14. package/src/blocks/OcBlockFeatures.vue +23 -23
  15. package/src/blocks/OcBlockFooter.vue +25 -25
  16. package/src/blocks/OcBlockFormPage.vue +24 -24
  17. package/src/blocks/OcBlockHero.vue +13 -13
  18. package/src/blocks/OcBlockHeroCode.vue +42 -42
  19. package/src/blocks/OcBlockHeroOrbit.vue +69 -69
  20. package/src/blocks/OcBlockHeroSplit.vue +15 -15
  21. package/src/blocks/OcBlockModuleHeader.vue +21 -21
  22. package/src/blocks/OcBlockPageHero.vue +13 -13
  23. package/src/blocks/OcBlockPortfolioGrid.vue +63 -63
  24. package/src/blocks/OcBlockPricing.vue +39 -39
  25. package/src/blocks/OcBlockProcess.vue +39 -39
  26. package/src/blocks/OcBlockProductGrid.vue +41 -41
  27. package/src/blocks/OcBlockProfileHeader.vue +50 -50
  28. package/src/blocks/OcBlockShowcase.vue +43 -43
  29. package/src/blocks/OcBlockSiteFooter.vue +54 -54
  30. package/src/blocks/OcBlockSiteHeader.vue +34 -34
  31. package/src/blocks/OcBlockSpotlight.vue +47 -47
  32. package/src/blocks/OcBlockStats.vue +17 -17
  33. package/src/blocks/OcBlockStatsCounter.vue +20 -20
  34. package/src/blocks/OcBlockTeamList.vue +53 -53
  35. package/src/blocks/OcBlockTwoFactor.vue +61 -61
  36. package/src/blocks/OcBlockWizardDialog.vue +67 -67
  37. package/src/components/OcAccordion.vue +12 -12
  38. package/src/components/OcAccordionAccent.vue +27 -27
  39. package/src/components/OcAccordionItem.vue +19 -19
  40. package/src/components/OcAffixInput.vue +40 -40
  41. package/src/components/OcAlert.vue +17 -17
  42. package/src/components/OcAlertDialog.vue +66 -66
  43. package/src/components/OcAlphaTabs.vue +54 -54
  44. package/src/components/OcAspectRatio.vue +21 -21
  45. package/src/components/OcAttachment.vue +59 -59
  46. package/src/components/OcAttachmentImage.vue +13 -13
  47. package/src/components/OcAttachmentList.vue +31 -31
  48. package/src/components/OcAttachmentThumb.vue +14 -14
  49. package/src/components/OcAvatar.vue +18 -18
  50. package/src/components/OcAvatarGroup.vue +7 -7
  51. package/src/components/OcBackLink.vue +8 -8
  52. package/src/components/OcBadge.vue +13 -13
  53. package/src/components/OcBarcodeInput.vue +51 -51
  54. package/src/components/OcBreadcrumb.vue +22 -22
  55. package/src/components/OcBrowserFrame.vue +33 -33
  56. package/src/components/OcBusyOverlay.vue +32 -32
  57. package/src/components/OcButton.vue +47 -47
  58. package/src/components/OcButtonGroup.vue +10 -10
  59. package/src/components/OcButtonGroupText.vue +7 -7
  60. package/src/components/OcCard.vue +20 -20
  61. package/src/components/OcChartLine.vue +80 -80
  62. package/src/components/OcChatComposer.vue +42 -42
  63. package/src/components/OcCheckbox.vue +26 -26
  64. package/src/components/OcChecklist.vue +29 -29
  65. package/src/components/OcCollapsible.vue +19 -19
  66. package/src/components/OcColorField.vue +15 -15
  67. package/src/components/OcColorSelect.vue +33 -33
  68. package/src/components/OcColumnMenu.vue +50 -50
  69. package/src/components/OcCommand.vue +119 -119
  70. package/src/components/OcConfirmDialog.vue +65 -65
  71. package/src/components/OcCookieConsent.vue +119 -119
  72. package/src/components/OcCopyField.vue +37 -37
  73. package/src/components/OcCounter.vue +15 -15
  74. package/src/components/OcDataTable.vue +144 -144
  75. package/src/components/OcDefinitionList.vue +35 -35
  76. package/src/components/OcDropdown.vue +23 -23
  77. package/src/components/OcDropdownItem.vue +9 -9
  78. package/src/components/OcDropdownLabel.vue +7 -7
  79. package/src/components/OcDropdownSeparator.vue +7 -7
  80. package/src/components/OcDropzone.vue +36 -36
  81. package/src/components/OcEmojiPicker.vue +45 -45
  82. package/src/components/OcEmptyState.vue +13 -13
  83. package/src/components/OcEntityCard.vue +47 -47
  84. package/src/components/OcFactList.vue +37 -37
  85. package/src/components/OcFilterCounts.vue +38 -38
  86. package/src/components/OcFlipCard.vue +36 -36
  87. package/src/components/OcFormField.vue +36 -36
  88. package/src/components/OcGreeting.vue +52 -52
  89. package/src/components/OcHeading.vue +19 -19
  90. package/src/components/OcHoverCard.vue +25 -25
  91. package/src/components/OcImageZoom.vue +39 -39
  92. package/src/components/OcInput.vue +9 -9
  93. package/src/components/OcInputGroup.vue +12 -12
  94. package/src/components/OcItem.vue +40 -40
  95. package/src/components/OcItemGroup.vue +7 -7
  96. package/src/components/OcItemSeparator.vue +7 -7
  97. package/src/components/OcKbd.vue +7 -7
  98. package/src/components/OcKbdGroup.vue +15 -15
  99. package/src/components/OcLabel.vue +10 -10
  100. package/src/components/OcLanguageSelect.vue +40 -40
  101. package/src/components/OcLauncherCard.vue +34 -34
  102. package/src/components/OcLightbox.vue +63 -63
  103. package/src/components/OcLinkArrow.vue +25 -25
  104. package/src/components/OcListToolbar.vue +44 -44
  105. package/src/components/OcMarquee.vue +36 -36
  106. package/src/components/OcMediaCard.vue +28 -28
  107. package/src/components/OcMediaRow.vue +28 -28
  108. package/src/components/OcMediaThumb.vue +38 -38
  109. package/src/components/OcMessage.vue +91 -91
  110. package/src/components/OcMessageList.vue +43 -43
  111. package/src/components/OcMessageThread.vue +155 -155
  112. package/src/components/OcModal.vue +42 -42
  113. package/src/components/OcNavmenu.vue +18 -18
  114. package/src/components/OcNavmenuList.vue +38 -38
  115. package/src/components/OcNextTeaser.vue +25 -25
  116. package/src/components/OcNumberInput.vue +47 -47
  117. package/src/components/OcOtpInput.vue +34 -34
  118. package/src/components/OcPageHeader.vue +34 -34
  119. package/src/components/OcPagination.vue +33 -33
  120. package/src/components/OcPasswordInput.vue +27 -27
  121. package/src/components/OcPasswordRequirements.vue +28 -28
  122. package/src/components/OcPhoneInput.vue +72 -72
  123. package/src/components/OcPopover.vue +25 -25
  124. package/src/components/OcPriceCard.vue +69 -69
  125. package/src/components/OcProductMark.vue +31 -31
  126. package/src/components/OcProgress.vue +21 -21
  127. package/src/components/OcProjectCard.vue +36 -36
  128. package/src/components/OcProse.vue +57 -57
  129. package/src/components/OcRadio.vue +40 -40
  130. package/src/components/OcRadioGroup.vue +32 -32
  131. package/src/components/OcRecoveryCodes.vue +55 -55
  132. package/src/components/OcScrollArea.vue +15 -15
  133. package/src/components/OcSegmented.vue +28 -28
  134. package/src/components/OcSelect.vue +21 -21
  135. package/src/components/OcSeparator.vue +18 -18
  136. package/src/components/OcSeverityCard.vue +46 -46
  137. package/src/components/OcSheet.vue +49 -49
  138. package/src/components/OcSidebarCollapsible.vue +19 -19
  139. package/src/components/OcSidebarGroup.vue +11 -11
  140. package/src/components/OcSidebarMenu.vue +7 -7
  141. package/src/components/OcSidebarMenuButton.vue +31 -31
  142. package/src/components/OcSidebarSeparator.vue +7 -7
  143. package/src/components/OcSkeleton.vue +8 -8
  144. package/src/components/OcSlider.vue +27 -27
  145. package/src/components/OcSortableRow.vue +40 -40
  146. package/src/components/OcSpinner.vue +13 -13
  147. package/src/components/OcStackCard.vue +24 -24
  148. package/src/components/OcStackList.vue +31 -31
  149. package/src/components/OcStatCard.vue +39 -39
  150. package/src/components/OcStepper.vue +34 -34
  151. package/src/components/OcSwitch.vue +15 -15
  152. package/src/components/OcTable.vue +115 -115
  153. package/src/components/OcTableActions.vue +26 -26
  154. package/src/components/OcTableCompact.vue +46 -46
  155. package/src/components/OcTabs.vue +37 -37
  156. package/src/components/OcTagInput.vue +50 -50
  157. package/src/components/OcTerminalLog.vue +50 -50
  158. package/src/components/OcTextarea.vue +9 -9
  159. package/src/components/OcThemeSwitch.vue +31 -31
  160. package/src/components/OcTimeInput.vue +50 -50
  161. package/src/components/OcTimeline.vue +36 -36
  162. package/src/components/OcToast.vue +31 -31
  163. package/src/components/OcToastContainer.vue +21 -21
  164. package/src/components/OcToggle.vue +63 -63
  165. package/src/components/OcToggleField.vue +28 -28
  166. package/src/components/OcToggleGroup.vue +40 -40
  167. package/src/components/OcTooltip.vue +8 -8
  168. package/src/components/OcTopProgress.vue +54 -54
  169. package/src/components/OcTree.vue +70 -70
  170. package/src/components/OcUpgradeBanner.vue +42 -42
  171. package/src/components/OcUser.vue +25 -25
  172. package/src/components/OcVersionBanner.vue +34 -34
  173. package/src/composables/chartLine.ts +28 -28
  174. package/src/composables/keys.ts +22 -22
  175. package/src/composables/useAttrsSplit.ts +16 -16
  176. package/src/composables/useDialog.ts +21 -21
  177. package/src/composables/useToast.ts +66 -66
  178. package/src/composables/useUid.ts +12 -12
@@ -1,144 +1,144 @@
1
- <!-- File: packages/vue/src/components/OcDataTable.vue | Map: props -> markup (toolbar, table, footer) -> bind the list-table script on mount -->
2
- <script setup lang="ts">
3
- /**
4
- * Korrekt / OmniaDesk list table. Same markup as packages/ui/snippets/data-table.html.
5
- * Search, sort, pages, columns, resize, drag and bulk actions come from data-table.js.
6
- * Listen on the root for oc-datatable-bulk, oc-datatable-reorder, oc-datatable-search, oc-datatable-import.
7
- */
8
- import { onMounted, useTemplateRef } from 'vue'
9
- import { bindDataTable } from '../../../ui/src/data-table.js'
10
-
11
- export interface DataTableColumn {
12
- key: string
13
- header: string
14
- numeric?: boolean
15
- sortable?: boolean
16
- hideable?: boolean
17
- defaultHidden?: boolean
18
- }
19
- export interface DataTableRow {
20
- key: string
21
- status?: 'active' | 'deleted' | 'archived'
22
- cells: Record<string, string>
23
- values?: Record<string, string>
24
- href?: string
25
- }
26
-
27
- const props = withDefaults(
28
- defineProps<{
29
- tableId?: string
30
- title?: string
31
- columns: DataTableColumn[]
32
- rows: DataTableRow[]
33
- pageSize?: number
34
- searchPlaceholder?: string
35
- selectable?: boolean
36
- draggable?: boolean
37
- filters?: boolean
38
- live?: boolean
39
- }>(),
40
- { title: 'List', pageSize: 15, searchPlaceholder: 'Search...', selectable: true, draggable: true, filters: true, live: false },
41
- )
42
-
43
- const root = useTemplateRef<HTMLElement>('root')
44
- const sizes = [...new Set([10, 15, 20, 50, 100, props.pageSize])].sort((a, b) => a - b)
45
- const lead = (props.selectable ? 1 : 0) + (props.draggable ? 1 : 0)
46
- const id = props.tableId || `oc-dt-${Math.random().toString(36).slice(2, 8)}`
47
-
48
- onMounted(() => {
49
- if (root.value) bindDataTable(root.value)
50
- })
51
- </script>
52
-
53
- <template>
54
- <div ref="root" class="oc-data-table oc-column-menu-scope" :id="id" :data-page-size="pageSize" :data-oc-live="live ? 'true' : undefined">
55
- <div class="oc-data-table-toolbar">
56
- <div class="oc-data-table-heading">
57
- <span class="oc-data-table-title">{{ title }}</span>
58
- <button class="oc-btn oc-btn--outline oc-btn--icon oc-btn--sm" type="button" :popovertarget="`${id}-menu`" aria-label="Table actions">⚙</button>
59
- <div class="oc-dropdown-menu" :id="`${id}-menu`" popover>
60
- <button class="oc-dropdown-item" type="button" data-oc-export>Export CSV</button>
61
- <button class="oc-dropdown-item" type="button" data-oc-import>Import CSV</button>
62
- <input class="oc-data-table-file" type="file" accept=".csv,text/csv" data-oc-file>
63
- <div class="oc-dropdown-separator"></div>
64
- <button class="oc-dropdown-item" type="button" data-oc-density="comfortable">Comfortable rows</button>
65
- <button class="oc-dropdown-item" type="button" data-oc-density="compact">Compact rows</button>
66
- <button class="oc-dropdown-item" type="button" data-oc-reset-widths>Reset column widths</button>
67
- </div>
68
- </div>
69
- <input class="oc-input oc-data-table-search" type="search" :placeholder="searchPlaceholder" :aria-label="`Search ${title}`">
70
- <div v-if="filters" class="oc-filter-pills" role="group" aria-label="Trash filter">
71
- <button class="oc-filter-pill" type="button" data-oc-filter="active" aria-current="true">Active only</button>
72
- <button class="oc-filter-pill" type="button" data-oc-filter="all">Including trash</button>
73
- <button class="oc-filter-pill" type="button" data-oc-filter="deleted">Trash only</button>
74
- <button class="oc-filter-pill" type="button" data-oc-filter="archived">Archive only</button>
75
- </div>
76
- <div class="oc-data-table-view" role="group" aria-label="View">
77
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-view="table" aria-pressed="true">Table</button>
78
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-view="grid">Cards</button>
79
- </div>
80
- <p class="oc-data-table-sort-summary" data-oc-sort-summary role="status"></p>
81
- </div>
82
- <div class="oc-table-toolbar">
83
- <span class="oc-table-toolbar-spacer"></span>
84
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" :popovertarget="`${id}-columns`">Columns</button>
85
- </div>
86
- <div class="oc-column-menu" :id="`${id}-columns`" popover>
87
- <p class="oc-column-menu-title">Visible columns</p>
88
- <form class="oc-column-menu-list">
89
- <template v-for="(col, index) in columns" :key="col.key">
90
- <label v-if="col.hideable !== false" class="oc-column-menu-item">
91
- <input type="checkbox" :data-col="lead + index + 1" :checked="!col.defaultHidden"> {{ col.header }}
92
- </label>
93
- </template>
94
- </form>
95
- </div>
96
- <div class="oc-data-table-bulk" hidden>
97
- <span data-oc-selected-count>0 selected</span>
98
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="export">Export selection</button>
99
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="duplicate">Duplicate</button>
100
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="archive">Move to trash</button>
101
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="restore">Restore</button>
102
- <button class="oc-btn oc-btn--destructive oc-btn--sm" type="button" data-oc-bulk="delete">Delete permanently</button>
103
- <button class="oc-btn oc-btn--ghost oc-btn--sm" type="button" data-oc-bulk="clear">Clear</button>
104
- </div>
105
- <div class="oc-data-table-frame">
106
- <div class="oc-data-table-scroll">
107
- <table class="oc-table oc-data-table-table">
108
- <thead>
109
- <tr>
110
- <th v-if="selectable" data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select-all aria-label="Select all"></th>
111
- <th v-if="draggable" data-oc-col="order"><span class="oc-visually-hidden">Order</span></th>
112
- <th v-for="col in columns" :key="col.key" :data-oc-col="col.key" :data-oc-sort="col.numeric ? 'numeric' : 'text'" :data-numeric="col.numeric ? '' : undefined">
113
- <span class="oc-data-table-th">
114
- <button v-if="col.sortable !== false" class="oc-table-sort" type="button">{{ col.header }}</button>
115
- <template v-else>{{ col.header }}</template>
116
- <span class="oc-data-table-resize" role="separator" aria-orientation="vertical" :aria-label="`Resize ${col.header}`"></span>
117
- </span>
118
- </th>
119
- <th data-oc-col="actions"><span class="oc-visually-hidden">Actions</span></th>
120
- </tr>
121
- </thead>
122
- <tbody>
123
- <tr v-for="row in rows" :key="row.key" data-oc-row :data-oc-key="row.key" :data-oc-status="row.status || 'active'" :data-oc-href="row.href">
124
- <td v-if="selectable" data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select :aria-label="`Select ${row.cells.name || row.key}`"></td>
125
- <td v-if="draggable" data-oc-col="order" class="oc-sortable-row-grip-cell"><button class="oc-sortable-row-grip" type="button" :aria-label="`Move ${row.cells.name || row.key}`"></button></td>
126
- <td v-for="col in columns" :key="col.key" :data-oc-col="col.key" :data-numeric="col.numeric ? '' : undefined" :data-oc-value="row.values?.[col.key]">{{ row.cells[col.key] ?? '' }}</td>
127
- <td data-oc-col="actions" class="oc-table-actions"><button class="oc-table-row-action" type="button">Edit</button></td>
128
- </tr>
129
- </tbody>
130
- </table>
131
- </div>
132
- <p class="oc-data-table-empty" hidden>No results</p>
133
- </div>
134
- <div class="oc-data-table-footer">
135
- <p class="oc-data-table-summary" data-oc-summary></p>
136
- <label class="oc-data-table-per-page">Rows per page
137
- <select class="oc-select" data-oc-page-size aria-label="Rows per page">
138
- <option v-for="n in sizes" :key="n" :value="n" :selected="n === pageSize">{{ n }}</option>
139
- </select>
140
- </label>
141
- <nav class="oc-data-table-pager" data-oc-pager aria-label="Pagination"></nav>
142
- </div>
143
- </div>
144
- </template>
1
+ <!-- File: packages/vue/src/components/OcDataTable.vue | Map: props -> markup (toolbar, table, footer) -> bind the list-table script on mount -->
2
+ <script setup lang="ts">
3
+ /**
4
+ * Korrekt / OmniaDesk list table. Same markup as packages/ui/snippets/data-table.html.
5
+ * Search, sort, pages, columns, resize, drag and bulk actions come from data-table.js.
6
+ * Listen on the root for oc-datatable-bulk, oc-datatable-reorder, oc-datatable-search, oc-datatable-import.
7
+ */
8
+ import { onMounted, useTemplateRef } from 'vue'
9
+ import { bindDataTable } from '../../../ui/src/data-table.js'
10
+
11
+ export interface DataTableColumn {
12
+ key: string
13
+ header: string
14
+ numeric?: boolean
15
+ sortable?: boolean
16
+ hideable?: boolean
17
+ defaultHidden?: boolean
18
+ }
19
+ export interface DataTableRow {
20
+ key: string
21
+ status?: 'active' | 'deleted' | 'archived'
22
+ cells: Record<string, string>
23
+ values?: Record<string, string>
24
+ href?: string
25
+ }
26
+
27
+ const props = withDefaults(
28
+ defineProps<{
29
+ tableId?: string
30
+ title?: string
31
+ columns: DataTableColumn[]
32
+ rows: DataTableRow[]
33
+ pageSize?: number
34
+ searchPlaceholder?: string
35
+ selectable?: boolean
36
+ draggable?: boolean
37
+ filters?: boolean
38
+ live?: boolean
39
+ }>(),
40
+ { title: 'List', pageSize: 15, searchPlaceholder: 'Search...', selectable: true, draggable: true, filters: true, live: false },
41
+ )
42
+
43
+ const root = useTemplateRef<HTMLElement>('root')
44
+ const sizes = [...new Set([10, 15, 20, 50, 100, props.pageSize])].sort((a, b) => a - b)
45
+ const lead = (props.selectable ? 1 : 0) + (props.draggable ? 1 : 0)
46
+ const id = props.tableId || `oc-dt-${Math.random().toString(36).slice(2, 8)}`
47
+
48
+ onMounted(() => {
49
+ if (root.value) bindDataTable(root.value)
50
+ })
51
+ </script>
52
+
53
+ <template>
54
+ <div ref="root" class="oc-data-table oc-column-menu-scope" :id="id" :data-page-size="pageSize" :data-oc-live="live ? 'true' : undefined">
55
+ <div class="oc-data-table-toolbar">
56
+ <div class="oc-data-table-heading">
57
+ <span class="oc-data-table-title">{{ title }}</span>
58
+ <button class="oc-btn oc-btn--outline oc-btn--icon oc-btn--sm" type="button" :popovertarget="`${id}-menu`" aria-label="Table actions">⚙</button>
59
+ <div class="oc-dropdown-menu" :id="`${id}-menu`" popover>
60
+ <button class="oc-dropdown-item" type="button" data-oc-export>Export CSV</button>
61
+ <button class="oc-dropdown-item" type="button" data-oc-import>Import CSV</button>
62
+ <input class="oc-data-table-file" type="file" accept=".csv,text/csv" data-oc-file>
63
+ <div class="oc-dropdown-separator"></div>
64
+ <button class="oc-dropdown-item" type="button" data-oc-density="comfortable">Comfortable rows</button>
65
+ <button class="oc-dropdown-item" type="button" data-oc-density="compact">Compact rows</button>
66
+ <button class="oc-dropdown-item" type="button" data-oc-reset-widths>Reset column widths</button>
67
+ </div>
68
+ </div>
69
+ <input class="oc-input oc-data-table-search" type="search" :placeholder="searchPlaceholder" :aria-label="`Search ${title}`">
70
+ <div v-if="filters" class="oc-filter-pills" role="group" aria-label="Trash filter">
71
+ <button class="oc-filter-pill" type="button" data-oc-filter="active" aria-current="true">Active only</button>
72
+ <button class="oc-filter-pill" type="button" data-oc-filter="all">Including trash</button>
73
+ <button class="oc-filter-pill" type="button" data-oc-filter="deleted">Trash only</button>
74
+ <button class="oc-filter-pill" type="button" data-oc-filter="archived">Archive only</button>
75
+ </div>
76
+ <div class="oc-data-table-view" role="group" aria-label="View">
77
+ <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-view="table" aria-pressed="true">Table</button>
78
+ <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-view="grid">Cards</button>
79
+ </div>
80
+ <p class="oc-data-table-sort-summary" data-oc-sort-summary role="status"></p>
81
+ </div>
82
+ <div class="oc-table-toolbar">
83
+ <span class="oc-table-toolbar-spacer"></span>
84
+ <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" :popovertarget="`${id}-columns`">Columns</button>
85
+ </div>
86
+ <div class="oc-column-menu" :id="`${id}-columns`" popover>
87
+ <p class="oc-column-menu-title">Visible columns</p>
88
+ <form class="oc-column-menu-list">
89
+ <template v-for="(col, index) in columns" :key="col.key">
90
+ <label v-if="col.hideable !== false" class="oc-column-menu-item">
91
+ <input type="checkbox" :data-col="lead + index + 1" :checked="!col.defaultHidden"> {{ col.header }}
92
+ </label>
93
+ </template>
94
+ </form>
95
+ </div>
96
+ <div class="oc-data-table-bulk" hidden>
97
+ <span data-oc-selected-count>0 selected</span>
98
+ <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="export">Export selection</button>
99
+ <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="duplicate">Duplicate</button>
100
+ <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="archive">Move to trash</button>
101
+ <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="restore">Restore</button>
102
+ <button class="oc-btn oc-btn--destructive oc-btn--sm" type="button" data-oc-bulk="delete">Delete permanently</button>
103
+ <button class="oc-btn oc-btn--ghost oc-btn--sm" type="button" data-oc-bulk="clear">Clear</button>
104
+ </div>
105
+ <div class="oc-data-table-frame">
106
+ <div class="oc-data-table-scroll">
107
+ <table class="oc-table oc-data-table-table">
108
+ <thead>
109
+ <tr>
110
+ <th v-if="selectable" data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select-all aria-label="Select all"></th>
111
+ <th v-if="draggable" data-oc-col="order"><span class="oc-visually-hidden">Order</span></th>
112
+ <th v-for="col in columns" :key="col.key" :data-oc-col="col.key" :data-oc-sort="col.numeric ? 'numeric' : 'text'" :data-numeric="col.numeric ? '' : undefined">
113
+ <span class="oc-data-table-th">
114
+ <button v-if="col.sortable !== false" class="oc-table-sort" type="button">{{ col.header }}</button>
115
+ <template v-else>{{ col.header }}</template>
116
+ <span class="oc-data-table-resize" role="separator" aria-orientation="vertical" :aria-label="`Resize ${col.header}`"></span>
117
+ </span>
118
+ </th>
119
+ <th data-oc-col="actions"><span class="oc-visually-hidden">Actions</span></th>
120
+ </tr>
121
+ </thead>
122
+ <tbody>
123
+ <tr v-for="row in rows" :key="row.key" data-oc-row :data-oc-key="row.key" :data-oc-status="row.status || 'active'" :data-oc-href="row.href">
124
+ <td v-if="selectable" data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select :aria-label="`Select ${row.cells.name || row.key}`"></td>
125
+ <td v-if="draggable" data-oc-col="order" class="oc-sortable-row-grip-cell"><button class="oc-sortable-row-grip" type="button" :aria-label="`Move ${row.cells.name || row.key}`"></button></td>
126
+ <td v-for="col in columns" :key="col.key" :data-oc-col="col.key" :data-numeric="col.numeric ? '' : undefined" :data-oc-value="row.values?.[col.key]">{{ row.cells[col.key] ?? '' }}</td>
127
+ <td data-oc-col="actions" class="oc-table-actions"><button class="oc-table-row-action" type="button">Edit</button></td>
128
+ </tr>
129
+ </tbody>
130
+ </table>
131
+ </div>
132
+ <p class="oc-data-table-empty" hidden>No results</p>
133
+ </div>
134
+ <div class="oc-data-table-footer">
135
+ <p class="oc-data-table-summary" data-oc-summary></p>
136
+ <label class="oc-data-table-per-page">Rows per page
137
+ <select class="oc-select" data-oc-page-size aria-label="Rows per page">
138
+ <option v-for="n in sizes" :key="n" :value="n" :selected="n === pageSize">{{ n }}</option>
139
+ </select>
140
+ </label>
141
+ <nav class="oc-data-table-pager" data-oc-pager aria-label="Pagination"></nav>
142
+ </div>
143
+ </div>
144
+ </template>
@@ -1,35 +1,35 @@
1
- <script setup lang="ts">
2
- /**
3
- * Label / value rows in a panel (dl). Pass `rows`, or put your own .oc-dl-row elements in the default slot.
4
- * Slots: title, description, default (rows), footer.
5
- */
6
- export interface DefinitionRow {
7
- term: string
8
- detail: string
9
- }
10
- withDefaults(
11
- defineProps<{
12
- title?: string
13
- description?: string
14
- rows?: DefinitionRow[]
15
- label?: string
16
- }>(),
17
- { rows: () => [] },
18
- )
19
- </script>
20
-
21
- <template>
22
- <div class="oc-dl-panel" role="region" :aria-label="label ?? title">
23
- <h3 v-if="title || $slots.title" class="oc-dl-title"><slot name="title">{{ title }}</slot></h3>
24
- <p v-if="description || $slots.description" class="oc-dl-description"><slot name="description">{{ description }}</slot></p>
25
- <dl class="oc-dl">
26
- <slot>
27
- <div v-for="(row, i) in rows" :key="i" class="oc-dl-row">
28
- <dt class="oc-dl-term">{{ row.term }}</dt>
29
- <dd class="oc-dl-detail">{{ row.detail }}</dd>
30
- </div>
31
- </slot>
32
- </dl>
33
- <div v-if="$slots.footer" class="oc-dl-footer"><slot name="footer" /></div>
34
- </div>
35
- </template>
1
+ <script setup lang="ts">
2
+ /**
3
+ * Label / value rows in a panel (dl). Pass `rows`, or put your own .oc-dl-row elements in the default slot.
4
+ * Slots: title, description, default (rows), footer.
5
+ */
6
+ export interface DefinitionRow {
7
+ term: string
8
+ detail: string
9
+ }
10
+ withDefaults(
11
+ defineProps<{
12
+ title?: string
13
+ description?: string
14
+ rows?: DefinitionRow[]
15
+ label?: string
16
+ }>(),
17
+ { rows: () => [] },
18
+ )
19
+ </script>
20
+
21
+ <template>
22
+ <div class="oc-dl-panel" role="region" :aria-label="label ?? title">
23
+ <h3 v-if="title || $slots.title" class="oc-dl-title"><slot name="title">{{ title }}</slot></h3>
24
+ <p v-if="description || $slots.description" class="oc-dl-description"><slot name="description">{{ description }}</slot></p>
25
+ <dl class="oc-dl">
26
+ <slot>
27
+ <div v-for="(row, i) in rows" :key="i" class="oc-dl-row">
28
+ <dt class="oc-dl-term">{{ row.term }}</dt>
29
+ <dd class="oc-dl-detail">{{ row.detail }}</dd>
30
+ </div>
31
+ </slot>
32
+ </dl>
33
+ <div v-if="$slots.footer" class="oc-dl-footer"><slot name="footer" /></div>
34
+ </div>
35
+ </template>
@@ -1,23 +1,23 @@
1
- <script setup lang="ts">
2
- /**
3
- * Dropdown menu on the popover attribute + anchor positioning. The trigger is the `trigger` slot
4
- * (scoped: { id }) or a default outline button showing `label`. Default slot = menu content
5
- * (OcDropdownLabel / OcDropdownItem / OcDropdownSeparator). Attributes land on the menu element.
6
- */
7
- import { useAttrs } from 'vue'
8
- import { useUid } from '../composables/useUid'
9
-
10
- defineOptions({ inheritAttrs: false })
11
- defineProps<{ label?: string }>()
12
- const attrs = useAttrs()
13
- const id = (attrs.id as string | undefined) ?? useUid('oc-menu')
14
- </script>
15
-
16
- <template>
17
- <slot name="trigger" :id="id">
18
- <button class="oc-btn oc-btn--outline" type="button" :popovertarget="id">{{ label }}</button>
19
- </slot>
20
- <div v-bind="attrs" :id="id" class="oc-dropdown-menu" popover>
21
- <slot />
22
- </div>
23
- </template>
1
+ <script setup lang="ts">
2
+ /**
3
+ * Dropdown menu on the popover attribute + anchor positioning. The trigger is the `trigger` slot
4
+ * (scoped: { id }) or a default outline button showing `label`. Default slot = menu content
5
+ * (OcDropdownLabel / OcDropdownItem / OcDropdownSeparator). Attributes land on the menu element.
6
+ */
7
+ import { useAttrs } from 'vue'
8
+ import { useUid } from '../composables/useUid'
9
+
10
+ defineOptions({ inheritAttrs: false })
11
+ defineProps<{ label?: string }>()
12
+ const attrs = useAttrs()
13
+ const id = (attrs.id as string | undefined) ?? useUid('oc-menu')
14
+ </script>
15
+
16
+ <template>
17
+ <slot name="trigger" :id="id">
18
+ <button class="oc-btn oc-btn--outline" type="button" :popovertarget="id">{{ label }}</button>
19
+ </slot>
20
+ <div v-bind="attrs" :id="id" class="oc-dropdown-menu" popover>
21
+ <slot />
22
+ </div>
23
+ </template>
@@ -1,9 +1,9 @@
1
- <script setup lang="ts">
2
- /** Menu item: <a> with `href`, otherwise <button>. */
3
- defineProps<{ href?: string }>()
4
- </script>
5
-
6
- <template>
7
- <a v-if="href" class="oc-dropdown-item" :href="href"><slot /></a>
8
- <button v-else class="oc-dropdown-item" type="button"><slot /></button>
9
- </template>
1
+ <script setup lang="ts">
2
+ /** Menu item: <a> with `href`, otherwise <button>. */
3
+ defineProps<{ href?: string }>()
4
+ </script>
5
+
6
+ <template>
7
+ <a v-if="href" class="oc-dropdown-item" :href="href"><slot /></a>
8
+ <button v-else class="oc-dropdown-item" type="button"><slot /></button>
9
+ </template>
@@ -1,7 +1,7 @@
1
- <script setup lang="ts">
2
- /** Heading inside a dropdown menu. */
3
- </script>
4
-
5
- <template>
6
- <div class="oc-dropdown-label"><slot /></div>
7
- </template>
1
+ <script setup lang="ts">
2
+ /** Heading inside a dropdown menu. */
3
+ </script>
4
+
5
+ <template>
6
+ <div class="oc-dropdown-label"><slot /></div>
7
+ </template>
@@ -1,7 +1,7 @@
1
- <script setup lang="ts">
2
- /** Divider inside a dropdown menu. */
3
- </script>
4
-
5
- <template>
6
- <div class="oc-dropdown-separator"></div>
7
- </template>
1
+ <script setup lang="ts">
2
+ /** Divider inside a dropdown menu. */
3
+ </script>
4
+
5
+ <template>
6
+ <div class="oc-dropdown-separator"></div>
7
+ </template>
@@ -1,36 +1,36 @@
1
- <script setup lang="ts">
2
- /**
3
- * File upload target: a label around a real file input. v-model: File[].
4
- * .is-dragover is toggled while dragging over. Slots: icon, default (text), hint.
5
- */
6
- import { ref } from 'vue'
7
- import { useAttrsSplit } from '../composables/useAttrsSplit'
8
-
9
- defineOptions({ inheritAttrs: false })
10
- defineProps<{ accept?: string; multiple?: boolean; disabled?: boolean; hint?: string }>()
11
- const model = defineModel<File[]>({ default: () => [] })
12
- const { root, control } = useAttrsSplit()
13
- const dragover = ref(false)
14
-
15
- function onChange(e: Event) {
16
- model.value = Array.from((e.target as HTMLInputElement).files ?? [])
17
- }
18
- function onDrop() {
19
- dragover.value = false
20
- }
21
- </script>
22
-
23
- <template>
24
- <label
25
- v-bind="root"
26
- :class="['oc-dropzone', dragover && 'is-dragover']"
27
- @dragover.prevent="dragover = true"
28
- @dragleave="dragover = false"
29
- @drop="onDrop"
30
- >
31
- <input v-bind="control" type="file" :accept="accept" :multiple="multiple" :disabled="disabled" @change="onChange" />
32
- <span v-if="$slots.icon" class="oc-dropzone-icon" aria-hidden="true"><slot name="icon" /></span>
33
- <span><slot /></span>
34
- <span v-if="hint || $slots.hint" class="oc-dropzone-hint"><slot name="hint">{{ hint }}</slot></span>
35
- </label>
36
- </template>
1
+ <script setup lang="ts">
2
+ /**
3
+ * File upload target: a label around a real file input. v-model: File[].
4
+ * .is-dragover is toggled while dragging over. Slots: icon, default (text), hint.
5
+ */
6
+ import { ref } from 'vue'
7
+ import { useAttrsSplit } from '../composables/useAttrsSplit'
8
+
9
+ defineOptions({ inheritAttrs: false })
10
+ defineProps<{ accept?: string; multiple?: boolean; disabled?: boolean; hint?: string }>()
11
+ const model = defineModel<File[]>({ default: () => [] })
12
+ const { root, control } = useAttrsSplit()
13
+ const dragover = ref(false)
14
+
15
+ function onChange(e: Event) {
16
+ model.value = Array.from((e.target as HTMLInputElement).files ?? [])
17
+ }
18
+ function onDrop() {
19
+ dragover.value = false
20
+ }
21
+ </script>
22
+
23
+ <template>
24
+ <label
25
+ v-bind="root"
26
+ :class="['oc-dropzone', dragover && 'is-dragover']"
27
+ @dragover.prevent="dragover = true"
28
+ @dragleave="dragover = false"
29
+ @drop="onDrop"
30
+ >
31
+ <input v-bind="control" type="file" :accept="accept" :multiple="multiple" :disabled="disabled" @change="onChange" />
32
+ <span v-if="$slots.icon" class="oc-dropzone-icon" aria-hidden="true"><slot name="icon" /></span>
33
+ <span><slot /></span>
34
+ <span v-if="hint || $slots.hint" class="oc-dropzone-hint"><slot name="hint">{{ hint }}</slot></span>
35
+ </label>
36
+ </template>
@@ -1,45 +1,45 @@
1
- <!-- File: packages/vue/src/components/OcEmojiPicker.vue | Map: props + emit -> trigger button -> popover panel -> groups (label + grid) -->
2
- <script setup lang="ts">
3
- /**
4
- * Emoji picker on the popover attribute (same markup as snippets/emoji-picker.html).
5
- * Props: groups ({ label?, emojis[] }[]), inline (always visible, no popover), triggerLabel, label.
6
- * Emits: select(emoji) and then closes the popover. Slot: trigger (button content, default 🙂).
7
- * Classes: .oc-emoji-picker(--inline), __trigger, __label, __grid, __item
8
- */
9
- import { useUid } from '../composables/useUid'
10
-
11
- withDefaults(
12
- defineProps<{ groups?: { label?: string; emojis: string[] }[]; inline?: boolean; triggerLabel?: string; label?: string }>(),
13
- {
14
- groups: () => [
15
- { label: 'Smileys', emojis: ['😀', '😃', '😄', '😁', '😂', '🙂', '😉', '😍', '🤔', '😎', '😢', '😴', '😯', '🥳', '😤', '🤗'] },
16
- { label: 'Gestures', emojis: ['👍', '👎', '👏', '🙌', '👋', '🙏', '✌️', '💪'] },
17
- { label: 'Objects', emojis: ['❤️', '⭐', '🔥', '🎉', '✅', '🚀', '💡', '☕'] },
18
- ],
19
- triggerLabel: 'Insert emoji',
20
- label: 'Emoji',
21
- },
22
- )
23
- const emit = defineEmits<{ select: [emoji: string] }>()
24
- const id = useUid('oc-emoji')
25
-
26
- function pick(e: MouseEvent, emoji: string) {
27
- emit('select', emoji)
28
- const panel = (e.currentTarget as HTMLElement).closest('[popover]') as (HTMLElement & { hidePopover?: () => void }) | null
29
- panel?.hidePopover?.()
30
- }
31
- </script>
32
-
33
- <template>
34
- <button v-if="!inline" type="button" class="oc-emoji-picker__trigger" :popovertarget="id" :aria-label="triggerLabel">
35
- <slot name="trigger">🙂</slot>
36
- </button>
37
- <div :id="id" :class="['oc-emoji-picker', inline && 'oc-emoji-picker--inline']" :popover="inline ? undefined : ''" :role="inline ? 'group' : undefined" :aria-label="label">
38
- <div v-for="(g, gi) in groups" :key="gi">
39
- <p v-if="g.label" class="oc-emoji-picker__label">{{ g.label }}</p>
40
- <div class="oc-emoji-picker__grid">
41
- <button v-for="emoji in g.emojis" :key="emoji" type="button" class="oc-emoji-picker__item" @click="pick($event, emoji)">{{ emoji }}</button>
42
- </div>
43
- </div>
44
- </div>
45
- </template>
1
+ <!-- File: packages/vue/src/components/OcEmojiPicker.vue | Map: props + emit -> trigger button -> popover panel -> groups (label + grid) -->
2
+ <script setup lang="ts">
3
+ /**
4
+ * Emoji picker on the popover attribute (same markup as snippets/emoji-picker.html).
5
+ * Props: groups ({ label?, emojis[] }[]), inline (always visible, no popover), triggerLabel, label.
6
+ * Emits: select(emoji) and then closes the popover. Slot: trigger (button content, default 🙂).
7
+ * Classes: .oc-emoji-picker(--inline), __trigger, __label, __grid, __item
8
+ */
9
+ import { useUid } from '../composables/useUid'
10
+
11
+ withDefaults(
12
+ defineProps<{ groups?: { label?: string; emojis: string[] }[]; inline?: boolean; triggerLabel?: string; label?: string }>(),
13
+ {
14
+ groups: () => [
15
+ { label: 'Smileys', emojis: ['😀', '😃', '😄', '😁', '😂', '🙂', '😉', '😍', '🤔', '😎', '😢', '😴', '😯', '🥳', '😤', '🤗'] },
16
+ { label: 'Gestures', emojis: ['👍', '👎', '👏', '🙌', '👋', '🙏', '✌️', '💪'] },
17
+ { label: 'Objects', emojis: ['❤️', '⭐', '🔥', '🎉', '✅', '🚀', '💡', '☕'] },
18
+ ],
19
+ triggerLabel: 'Insert emoji',
20
+ label: 'Emoji',
21
+ },
22
+ )
23
+ const emit = defineEmits<{ select: [emoji: string] }>()
24
+ const id = useUid('oc-emoji')
25
+
26
+ function pick(e: MouseEvent, emoji: string) {
27
+ emit('select', emoji)
28
+ const panel = (e.currentTarget as HTMLElement).closest('[popover]') as (HTMLElement & { hidePopover?: () => void }) | null
29
+ panel?.hidePopover?.()
30
+ }
31
+ </script>
32
+
33
+ <template>
34
+ <button v-if="!inline" type="button" class="oc-emoji-picker__trigger" :popovertarget="id" :aria-label="triggerLabel">
35
+ <slot name="trigger">🙂</slot>
36
+ </button>
37
+ <div :id="id" :class="['oc-emoji-picker', inline && 'oc-emoji-picker--inline']" :popover="inline ? undefined : ''" :role="inline ? 'group' : undefined" :aria-label="label">
38
+ <div v-for="(g, gi) in groups" :key="gi">
39
+ <p v-if="g.label" class="oc-emoji-picker__label">{{ g.label }}</p>
40
+ <div class="oc-emoji-picker__grid">
41
+ <button v-for="emoji in g.emojis" :key="emoji" type="button" class="oc-emoji-picker__item" @click="pick($event, emoji)">{{ emoji }}</button>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </template>