@alfakit/vue 0.1.0 → 0.1.2

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 (136) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/components/actions/ActionButton.js.map +1 -1
  3. package/dist/components/actions/ActionButton.vue.d.ts.map +1 -1
  4. package/dist/components/actions/ActionButton.vue_vue_type_script_setup_true_lang.js +160 -159
  5. package/dist/components/actions/ActionButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/actions/ActionModal.js.map +1 -1
  7. package/dist/components/actions/ActionModal.vue.d.ts.map +1 -1
  8. package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js +214 -214
  9. package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js.map +1 -1
  10. package/dist/components/cms/CmsLinkButton.vue.d.ts +1 -1
  11. package/dist/components/fields/ColorPickerField.js.map +1 -1
  12. package/dist/components/fields/ColorPickerField.vue.d.ts.map +1 -1
  13. package/dist/components/fields/ColorPickerField.vue_vue_type_script_setup_true_lang.js +1 -0
  14. package/dist/components/fields/ColorPickerField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  15. package/dist/components/fields/ComboboxSelect.js.map +1 -1
  16. package/dist/components/fields/ComboboxSelect.vue.d.ts.map +1 -1
  17. package/dist/components/fields/ComboboxSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  18. package/dist/components/fields/ComboboxSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/fields/FileUploadField.js.map +1 -1
  20. package/dist/components/fields/FileUploadField.vue.d.ts.map +1 -1
  21. package/dist/components/fields/FileUploadField.vue_vue_type_script_setup_true_lang.js +183 -183
  22. package/dist/components/fields/FileUploadField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  23. package/dist/components/fields/OneTimeCodeInputField.js.map +1 -1
  24. package/dist/components/fields/OneTimeCodeInputField.vue_vue_type_script_setup_true_lang.js +1 -2
  25. package/dist/components/fields/OneTimeCodeInputField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  26. package/dist/components/fields/SelectField.js.map +1 -1
  27. package/dist/components/fields/SelectField.vue.d.ts.map +1 -1
  28. package/dist/components/fields/SelectField.vue_vue_type_script_setup_true_lang.js +2 -2
  29. package/dist/components/fields/SelectField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/components/fields/TableColumnHeaders.js.map +1 -1
  31. package/dist/components/fields/TableColumnHeaders.vue.d.ts.map +1 -1
  32. package/dist/components/fields/TableColumnHeaders.vue_vue_type_script_setup_true_lang.js +6 -3
  33. package/dist/components/fields/TableColumnHeaders.vue_vue_type_script_setup_true_lang.js.map +1 -1
  34. package/dist/components/file-manager/FileManagerView.js.map +1 -1
  35. package/dist/components/file-manager/FileManagerView.vue_vue_type_script_setup_true_lang.js +1 -1
  36. package/dist/components/file-manager/FileManagerView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/components/form/FormBlock.js.map +1 -1
  38. package/dist/components/form/FormBlock.vue.d.ts.map +1 -1
  39. package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js +81 -77
  40. package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/form/form-context.js +25 -25
  42. package/dist/components/form/form-context.js.map +1 -1
  43. package/dist/components/layout/FusedGroupComponent.js.map +1 -1
  44. package/dist/components/layout/FusedGroupComponent.vue.d.ts.map +1 -1
  45. package/dist/components/layout/FusedGroupComponent.vue_vue_type_script_setup_true_lang.js +1 -0
  46. package/dist/components/layout/FusedGroupComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  47. package/dist/components/layout/TabsComponent.js.map +1 -1
  48. package/dist/components/layout/TabsComponent.vue.d.ts.map +1 -1
  49. package/dist/components/layout/TabsComponent.vue_vue_type_script_setup_true_lang.js +76 -55
  50. package/dist/components/layout/TabsComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  51. package/dist/components/notifications/NotificationsMenu.js.map +1 -1
  52. package/dist/components/notifications/NotificationsMenu.vue.d.ts.map +1 -1
  53. package/dist/components/notifications/NotificationsMenu.vue_vue_type_script_setup_true_lang.js +44 -42
  54. package/dist/components/notifications/NotificationsMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  55. package/dist/components/panel/GlobalSearch.js.map +1 -1
  56. package/dist/components/panel/GlobalSearch.vue.d.ts.map +1 -1
  57. package/dist/components/panel/GlobalSearch.vue_vue_type_script_setup_true_lang.js +1 -0
  58. package/dist/components/panel/GlobalSearch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  59. package/dist/components/panel/ShortcutKeys.js.map +1 -1
  60. package/dist/components/panel/ShortcutKeys.vue.d.ts.map +1 -1
  61. package/dist/components/panel/ShortcutKeys.vue_vue_type_script_setup_true_lang.js +4 -1
  62. package/dist/components/panel/ShortcutKeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/panel/TenantMenu.js.map +1 -1
  64. package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js +2 -2
  65. package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/table/GroupHeaderRow.js.map +1 -1
  67. package/dist/components/table/GroupHeaderRow.vue.d.ts.map +1 -1
  68. package/dist/components/table/GroupHeaderRow.vue_vue_type_script_setup_true_lang.js +55 -34
  69. package/dist/components/table/GroupHeaderRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/table/SelectCell.js.map +1 -1
  71. package/dist/components/table/SelectCell.vue.d.ts.map +1 -1
  72. package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js +24 -19
  73. package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/table/TextInputCell.js.map +1 -1
  75. package/dist/components/table/TextInputCell.vue.d.ts.map +1 -1
  76. package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js +38 -33
  77. package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  78. package/dist/components.css +347 -0
  79. package/dist/eject-manifest.json +2 -2
  80. package/dist/lib/Icon.js.map +1 -1
  81. package/dist/lib/Icon.vue.d.ts.map +1 -1
  82. package/dist/lib/Icon.vue_vue_type_script_setup_true_lang.js +18 -19
  83. package/dist/lib/Icon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  84. package/dist/lib/hydration.d.ts +9 -0
  85. package/dist/lib/hydration.d.ts.map +1 -0
  86. package/dist/lib/hydration.js +17 -0
  87. package/dist/lib/hydration.js.map +1 -0
  88. package/dist/lib/icons.d.ts +3 -5
  89. package/dist/lib/icons.d.ts.map +1 -1
  90. package/dist/lib/icons.js +19 -22
  91. package/dist/lib/icons.js.map +1 -1
  92. package/dist/lib/lazy.d.ts +1 -1
  93. package/dist/lib/lazy.d.ts.map +1 -1
  94. package/dist/lib/lazy.js +12 -11
  95. package/dist/lib/lazy.js.map +1 -1
  96. package/dist/standalone/AlfakitToaster.js.map +1 -1
  97. package/dist/standalone/AlfakitToaster.vue.d.ts.map +1 -1
  98. package/dist/standalone/AlfakitToaster.vue_vue_type_script_setup_true_lang.js +23 -15
  99. package/dist/standalone/AlfakitToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  100. package/dist/standalone.css +47 -0
  101. package/dist/starter-kit/widgets/SearchTrigger.js.map +1 -1
  102. package/dist/starter-kit/widgets/SearchTrigger.vue.d.ts.map +1 -1
  103. package/dist/starter-kit/widgets/SearchTrigger.vue_vue_type_script_setup_true_lang.js +1 -0
  104. package/dist/starter-kit/widgets/SearchTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/starter-kit/widgets/TenantChooser.js.map +1 -1
  106. package/dist/starter-kit/widgets/TenantChooser.vue_vue_type_script_setup_true_lang.js +1 -1
  107. package/dist/starter-kit/widgets/TenantChooser.vue_vue_type_script_setup_true_lang.js.map +1 -1
  108. package/dist/themes.css +2 -334
  109. package/package.json +3 -3
  110. package/src/components/actions/ActionButton.vue +14 -6
  111. package/src/components/actions/ActionModal.vue +3 -1
  112. package/src/components/fields/ColorPickerField.vue +1 -0
  113. package/src/components/fields/ComboboxSelect.vue +1 -1
  114. package/src/components/fields/FileUploadField.vue +14 -11
  115. package/src/components/fields/OneTimeCodeInputField.vue +1 -1
  116. package/src/components/fields/SelectField.vue +4 -2
  117. package/src/components/fields/TableColumnHeaders.vue +6 -1
  118. package/src/components/file-manager/FileManagerView.vue +1 -1
  119. package/src/components/form/FormBlock.vue +24 -0
  120. package/src/components/form/form-context.ts +2 -2
  121. package/src/components/layout/FusedGroupComponent.vue +1 -0
  122. package/src/components/layout/TabsComponent.vue +61 -5
  123. package/src/components/notifications/NotificationsMenu.vue +11 -0
  124. package/src/components/panel/GlobalSearch.vue +1 -0
  125. package/src/components/panel/ShortcutKeys.vue +1 -0
  126. package/src/components/panel/TenantMenu.vue +2 -2
  127. package/src/components/table/GroupHeaderRow.vue +27 -0
  128. package/src/components/table/SelectCell.vue +5 -2
  129. package/src/components/table/TextInputCell.vue +11 -5
  130. package/src/lib/Icon.vue +6 -5
  131. package/src/lib/hydration.ts +35 -0
  132. package/src/lib/icons.ts +6 -11
  133. package/src/lib/lazy.ts +5 -6
  134. package/src/standalone/AlfakitToaster.vue +12 -2
  135. package/src/starter-kit/widgets/SearchTrigger.vue +1 -0
  136. package/src/starter-kit/widgets/TenantChooser.vue +1 -1
@@ -70,7 +70,7 @@ var M = {
70
70
  default: k(() => [C(O(n), {
71
71
  name: "alfakit::panels.tenant-menu.registration-button",
72
72
  fallback: O(j)
73
- }, null, 8, ["fallback"]), S(" " + D(O(P)("tenancy.register", {}, "New")), 1)]),
73
+ }, null, 8, ["fallback"]), S(" " + D(I.value.registrationLabel ?? O(P)("tenancy.register", {}, "New")), 1)]),
74
74
  _: 1
75
75
  })], 64)) : y("", !0)
76
76
  ]),
@@ -1 +1 @@
1
- {"version":3,"file":"TenantChooser.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","DropdownMenu","_withCtx","_createVNode","DropdownMenuTrigger","_createElementVNode","_toDisplayString","_unref","Icon","DropdownMenuContent","DropdownMenuLabel","_createTextVNode","_createCommentVNode","_createElementBlock","_Fragment","_renderList","DropdownMenuItem","Avatar","AvatarImage","AvatarFallback","NavLabel","DropdownMenuSeparator","Icon_default","DropdownMenu_default","DropdownMenuContent_default","DropdownMenuItem_default","DropdownMenuSeparator_default","DropdownMenuTrigger_default","DropdownMenuLabel_default","NavLabel_default","Avatar_default","AvatarFallback_default","AvatarImage_default","_hoisted_1","_hoisted_2","TenantChooser_vue_vue_type_script_setup_true_lang_default","t","useT","panel","usePanel","tenancy","computed","label","visible","openBlock","createBlock","withCtx","createVNode","createElementVNode","toDisplayString","unref","ChevronsUpDownIcon","createTextVNode","createCommentVNode","createElementBlock","Fragment","renderList","tenant","router","initials","tenantNameText","_cache","PlusIcon"],"sources":["../../../src/starter-kit/widgets/TenantChooser.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { initials, tenantNameText } from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { ChevronsUpDownIcon, PlusIcon } from '@lucide/vue'\nimport { computed } from 'vue'\nimport NavLabel from '../../components/panel/NavLabel.vue'\nimport Avatar from '../../components/ui/Avatar.vue'\nimport AvatarFallback from '../../components/ui/AvatarFallback.vue'\nimport AvatarImage from '../../components/ui/AvatarImage.vue'\nimport DropdownMenu from '../../components/ui/DropdownMenu.vue'\nimport DropdownMenuContent from '../../components/ui/DropdownMenuContent.vue'\nimport DropdownMenuItem from '../../components/ui/DropdownMenuItem.vue'\nimport DropdownMenuLabel from '../../components/ui/DropdownMenuLabel.vue'\nimport DropdownMenuSeparator from '../../components/ui/DropdownMenuSeparator.vue'\nimport DropdownMenuTrigger from '../../components/ui/DropdownMenuTrigger.vue'\nimport { usePanel, useT } from '../../context'\nimport { Icon } from '../../lib/icons'\n\n/** The user's tenants on a page outside the panel (no current tenant). */\nconst t = useT()\nconst panel = usePanel()\nconst tenancy = computed(() => panel.value.tenancy)\nconst label = computed(() => t('starter_kit.choose_tenant', {}, 'Choose a tenant'))\nconst visible = computed(\n () => !!tenancy.value && (tenancy.value.tenants.length > 0 || !!tenancy.value.registrationUrl),\n)\n</script>\n\n<template>\n <DropdownMenu v-if=\"tenancy && visible\">\n <DropdownMenuTrigger as-child>\n <button\n type=\"button\"\n data-slot=\"tenant-menu\"\n class=\"hover:bg-accent data-[state=open]:bg-accent inline-flex h-9 max-w-60 shrink-0 items-center gap-2 rounded-md px-2 text-sm font-medium\"\n >\n <span class=\"sr-only lg:not-sr-only lg:truncate\">{{ label }}</span>\n <Icon\n name=\"alfakit::panels.tenant-menu.toggle-button\"\n :fallback=\"ChevronsUpDownIcon\"\n class=\"text-muted-foreground size-4 shrink-0\"\n />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent class=\"min-w-56 rounded-lg\" side=\"bottom\" align=\"end\" :side-offset=\"4\">\n <DropdownMenuLabel v-if=\"tenancy.tenants.length > 0\" class=\"text-muted-foreground text-xs\">{{\n label\n }}</DropdownMenuLabel>\n <DropdownMenuItem\n v-for=\"tenant in tenancy.tenants\"\n :key=\"String(tenant.id)\"\n @select=\"router.visit(tenant.url)\"\n >\n <Avatar class=\"size-6 rounded-sm\">\n <AvatarImage v-if=\"tenant.avatar\" :src=\"tenant.avatar\" alt=\"\" />\n <AvatarFallback class=\"rounded-sm text-[10px]\">{{\n initials(tenantNameText(tenant))\n }}</AvatarFallback>\n </Avatar>\n <NavLabel class=\"flex-1 truncate\" :text=\"tenant.name\" :html=\"tenant.nameHtml\" />\n </DropdownMenuItem>\n <template v-if=\"tenancy.registrationUrl\">\n <DropdownMenuSeparator v-if=\"tenancy.tenants.length > 0\" />\n <DropdownMenuItem @select=\"router.visit(tenancy.registrationUrl!)\">\n <Icon name=\"alfakit::panels.tenant-menu.registration-button\" :fallback=\"PlusIcon\" />\n {{ t('tenancy.register', {}, 'New') }}\n </DropdownMenuItem>\n </template>\n </DropdownMenuContent>\n </DropdownMenu>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;EAmBA,IAAMqC,IAAIC,EAAK,GACTC,IAAQC,EAAS,GACjBC,IAAUC,QAAeH,EAAM,MAAM,OAAO,GAC5CI,IAAQD,QAAeL,EAAE,6BAA6B,CAAC,GAAG,iBAAiB,CAAC,GAC5EO,IAAUF,QACR,CAAC,CAACD,EAAQ,UAAUA,EAAQ,MAAM,QAAQ,SAAS,KAAK,CAAC,CAACA,EAAQ,MAAM,gBAChF;mBAIsBA,EAAA,SAAWG,EAAA,SAA/B5C,EAAA,GAAAC,EAwCeC,GAAA,EAAA,KAAA,EAAA,GAAA;GAvCb,SAAAC,QAasB,CAbtBC,EAasBC,GAAA,EAbD,YAAA,GAAQ,GAAA;IAC3B,SAAAF,QAWS,CAXTG,EAWS,UAXT4B,GAWS,CANP5B,EAAmE,QAAnE6B,GAAmE5B,EAAfoC,EAAA,KAAK,GAAA,CAAA,GACzDvC,EAIEI,EAAAC,CAAA,GAAA;KAHA,MAAK;KACJ,UAAUD,EAAA4C,CAAA;KACX,OAAM;;;GAIZhD,CAAAA,GAAAA,EAwBsBM,GAAA;IAxBD,OAAM;IAAsB,MAAK;IAAS,OAAM;IAAO,eAAa;;IACvF,SAAAP,QAEsB;KAFGsC,EAAA,MAAQ,QAAQ,SAAM,KAA/CzC,EAAA,GAAAC,EAEsBU,GAAA;;MAF+B,OAAM;;MAAgC,SAAAR,QAEzF,CADAS,EAAAL,EAAAoC,EAAA,KAAK,GAAA,CAAA,CAAA,CAAA;;;MAEP3C,EAAA,EAAA,GAAAc,EAYmBC,GAAA,MAAAC,EAXAyB,EAAA,MAAQ,UAAlB,OADTzC,EAAA,GAAAC,EAYmBgB,GAAA;MAVhB,KAAK,OAAOyC,EAAO,EAAE;MACrB,WAAM,MAAElD,EAAAmD,CAAA,CAAM,CAAC,MAAMD,EAAO,GAAG;;MAEhC,SAAAvD,QAKS,CALTC,EAKSc,GAAA,EALD,OAAM,oBAAmB,GAAA;OAC/B,SAAAf,QAAgE,CAA7CuD,EAAO,UAA1B1D,EAAA,GAAAC,EAAgEkB,GAAA;;QAA7B,KAAKuC,EAAO;QAAQ,KAAI;OAC3DtD,GAAAA,MAAAA,GAAAA,CAAAA,KAAAA,CAAAA,KAAAA,EAAAA,IAAAA,EAAAA,GAAAA,EAEmBgB,GAAA,EAFH,OAAM,yBAAwB,GAAA;QAAC,SAAAjB,QAE7C,CADAS,EAAAL,EAAAC,EAAAoD,CAAA,CAAQ,CAACpD,EAAAqD,CAAA,CAAc,CAACH,CAAM,CAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;;MAGlCtD,GAAAA,IAAAA,GAAAA,EAAgFiB,GAAA;OAAtE,OAAM;OAAmB,MAAMqC,EAAO;OAAO,MAAMA,EAAO;;;;KAEtDjB,EAAA,MAAQ,mBAAxBzC,EAAA,GAAAc,EAMWC,GAAA,EAAA,KAAA,EAAA,GAAA,CALoB0B,EAAA,MAAQ,QAAQ,SAAM,KAAnDzC,EAAA,GAAAC,EAA2DqB,GAAA,EAAA,KAAA,EAAA,CAAA,KAAAgC,EAAA,IAAA,EAAA,GAC3DlD,EAGmBa,GAAA,EAHA,UAAM,AAAA6C,EAAA,QAAA,MAAEtD,EAAAmD,CAAA,CAAM,CAAC,MAAMlB,EAAA,MAAQ,eAAe,EAAA,GAAA;MAC7D,SAAAtC,QAAoF,CAApFC,EAAoFI,EAAAC,CAAA,GAAA;OAA9E,MAAK;OAAmD,UAAUD,EAAAuD,CAAA;MAAYnD,GAAAA,MAAAA,GAAAA,CAAAA,UAAAA,CAAAA,GAAAA,EAAA,MACpFL,EAAGC,EAAA6B,CAAA,CAAC,CAAA,oBAAA,CAAA,GAAA,KAAA,CAAA,GAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"TenantChooser.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","DropdownMenu","_withCtx","_createVNode","DropdownMenuTrigger","_createElementVNode","_toDisplayString","_unref","Icon","DropdownMenuContent","DropdownMenuLabel","_createTextVNode","_createCommentVNode","_createElementBlock","_Fragment","_renderList","DropdownMenuItem","Avatar","AvatarImage","AvatarFallback","NavLabel","DropdownMenuSeparator","Icon_default","DropdownMenu_default","DropdownMenuContent_default","DropdownMenuItem_default","DropdownMenuSeparator_default","DropdownMenuTrigger_default","DropdownMenuLabel_default","NavLabel_default","Avatar_default","AvatarFallback_default","AvatarImage_default","_hoisted_1","_hoisted_2","TenantChooser_vue_vue_type_script_setup_true_lang_default","t","useT","panel","usePanel","tenancy","computed","label","visible","openBlock","createBlock","withCtx","createVNode","createElementVNode","toDisplayString","unref","ChevronsUpDownIcon","createTextVNode","createCommentVNode","createElementBlock","Fragment","renderList","tenant","router","initials","tenantNameText","_cache","PlusIcon"],"sources":["../../../src/starter-kit/widgets/TenantChooser.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { initials, tenantNameText } from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { ChevronsUpDownIcon, PlusIcon } from '@lucide/vue'\nimport { computed } from 'vue'\nimport NavLabel from '../../components/panel/NavLabel.vue'\nimport Avatar from '../../components/ui/Avatar.vue'\nimport AvatarFallback from '../../components/ui/AvatarFallback.vue'\nimport AvatarImage from '../../components/ui/AvatarImage.vue'\nimport DropdownMenu from '../../components/ui/DropdownMenu.vue'\nimport DropdownMenuContent from '../../components/ui/DropdownMenuContent.vue'\nimport DropdownMenuItem from '../../components/ui/DropdownMenuItem.vue'\nimport DropdownMenuLabel from '../../components/ui/DropdownMenuLabel.vue'\nimport DropdownMenuSeparator from '../../components/ui/DropdownMenuSeparator.vue'\nimport DropdownMenuTrigger from '../../components/ui/DropdownMenuTrigger.vue'\nimport { usePanel, useT } from '../../context'\nimport { Icon } from '../../lib/icons'\n\n/** The user's tenants on a page outside the panel (no current tenant). */\nconst t = useT()\nconst panel = usePanel()\nconst tenancy = computed(() => panel.value.tenancy)\nconst label = computed(() => t('starter_kit.choose_tenant', {}, 'Choose a tenant'))\nconst visible = computed(\n () => !!tenancy.value && (tenancy.value.tenants.length > 0 || !!tenancy.value.registrationUrl),\n)\n</script>\n\n<template>\n <DropdownMenu v-if=\"tenancy && visible\">\n <DropdownMenuTrigger as-child>\n <button\n type=\"button\"\n data-slot=\"tenant-menu\"\n class=\"hover:bg-accent data-[state=open]:bg-accent inline-flex h-9 max-w-60 shrink-0 items-center gap-2 rounded-md px-2 text-sm font-medium\"\n >\n <span class=\"sr-only lg:not-sr-only lg:truncate\">{{ label }}</span>\n <Icon\n name=\"alfakit::panels.tenant-menu.toggle-button\"\n :fallback=\"ChevronsUpDownIcon\"\n class=\"text-muted-foreground size-4 shrink-0\"\n />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent class=\"min-w-56 rounded-lg\" side=\"bottom\" align=\"end\" :side-offset=\"4\">\n <DropdownMenuLabel v-if=\"tenancy.tenants.length > 0\" class=\"text-muted-foreground text-xs\">{{\n label\n }}</DropdownMenuLabel>\n <DropdownMenuItem\n v-for=\"tenant in tenancy.tenants\"\n :key=\"String(tenant.id)\"\n @select=\"router.visit(tenant.url)\"\n >\n <Avatar class=\"size-6 rounded-sm\">\n <AvatarImage v-if=\"tenant.avatar\" :src=\"tenant.avatar\" alt=\"\" />\n <AvatarFallback class=\"rounded-sm text-[10px]\">{{\n initials(tenantNameText(tenant))\n }}</AvatarFallback>\n </Avatar>\n <NavLabel class=\"flex-1 truncate\" :text=\"tenant.name\" :html=\"tenant.nameHtml\" />\n </DropdownMenuItem>\n <template v-if=\"tenancy.registrationUrl\">\n <DropdownMenuSeparator v-if=\"tenancy.tenants.length > 0\" />\n <DropdownMenuItem @select=\"router.visit(tenancy.registrationUrl!)\">\n <Icon name=\"alfakit::panels.tenant-menu.registration-button\" :fallback=\"PlusIcon\" />\n {{ tenancy.registrationLabel ?? t('tenancy.register', {}, 'New') }}\n </DropdownMenuItem>\n </template>\n </DropdownMenuContent>\n </DropdownMenu>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;EAmBA,IAAMqC,IAAIC,EAAK,GACTC,IAAQC,EAAS,GACjBC,IAAUC,QAAeH,EAAM,MAAM,OAAO,GAC5CI,IAAQD,QAAeL,EAAE,6BAA6B,CAAC,GAAG,iBAAiB,CAAC,GAC5EO,IAAUF,QACR,CAAC,CAACD,EAAQ,UAAUA,EAAQ,MAAM,QAAQ,SAAS,KAAK,CAAC,CAACA,EAAQ,MAAM,gBAChF;mBAIsBA,EAAA,SAAWG,EAAA,SAA/B5C,EAAA,GAAAC,EAwCeC,GAAA,EAAA,KAAA,EAAA,GAAA;GAvCb,SAAAC,QAasB,CAbtBC,EAasBC,GAAA,EAbD,YAAA,GAAQ,GAAA;IAC3B,SAAAF,QAWS,CAXTG,EAWS,UAXT4B,GAWS,CANP5B,EAAmE,QAAnE6B,GAAmE5B,EAAfoC,EAAA,KAAK,GAAA,CAAA,GACzDvC,EAIEI,EAAAC,CAAA,GAAA;KAHA,MAAK;KACJ,UAAUD,EAAA4C,CAAA;KACX,OAAM;;;GAIZhD,CAAAA,GAAAA,EAwBsBM,GAAA;IAxBD,OAAM;IAAsB,MAAK;IAAS,OAAM;IAAO,eAAa;;IACvF,SAAAP,QAEsB;KAFGsC,EAAA,MAAQ,QAAQ,SAAM,KAA/CzC,EAAA,GAAAC,EAEsBU,GAAA;;MAF+B,OAAM;;MAAgC,SAAAR,QAEzF,CADAS,EAAAL,EAAAoC,EAAA,KAAK,GAAA,CAAA,CAAA,CAAA;;;MAEP3C,EAAA,EAAA,GAAAc,EAYmBC,GAAA,MAAAC,EAXAyB,EAAA,MAAQ,UAAlB,OADTzC,EAAA,GAAAC,EAYmBgB,GAAA;MAVhB,KAAK,OAAOyC,EAAO,EAAE;MACrB,WAAM,MAAElD,EAAAmD,CAAA,CAAM,CAAC,MAAMD,EAAO,GAAG;;MAEhC,SAAAvD,QAKS,CALTC,EAKSc,GAAA,EALD,OAAM,oBAAmB,GAAA;OAC/B,SAAAf,QAAgE,CAA7CuD,EAAO,UAA1B1D,EAAA,GAAAC,EAAgEkB,GAAA;;QAA7B,KAAKuC,EAAO;QAAQ,KAAI;OAC3DtD,GAAAA,MAAAA,GAAAA,CAAAA,KAAAA,CAAAA,KAAAA,EAAAA,IAAAA,EAAAA,GAAAA,EAEmBgB,GAAA,EAFH,OAAM,yBAAwB,GAAA;QAAC,SAAAjB,QAE7C,CADAS,EAAAL,EAAAC,EAAAoD,CAAA,CAAQ,CAACpD,EAAAqD,CAAA,CAAc,CAACH,CAAM,CAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;;MAGlCtD,GAAAA,IAAAA,GAAAA,EAAgFiB,GAAA;OAAtE,OAAM;OAAmB,MAAMqC,EAAO;OAAO,MAAMA,EAAO;;;;KAEtDjB,EAAA,MAAQ,mBAAxBzC,EAAA,GAAAc,EAMWC,GAAA,EAAA,KAAA,EAAA,GAAA,CALoB0B,EAAA,MAAQ,QAAQ,SAAM,KAAnDzC,EAAA,GAAAC,EAA2DqB,GAAA,EAAA,KAAA,EAAA,CAAA,KAAAgC,EAAA,IAAA,EAAA,GAC3DlD,EAGmBa,GAAA,EAHA,UAAM,AAAA6C,EAAA,QAAA,MAAEtD,EAAAmD,CAAA,CAAM,CAAC,MAAMlB,EAAA,MAAQ,eAAe,EAAA,GAAA;MAC7D,SAAAtC,QAAoF,CAApFC,EAAoFI,EAAAC,CAAA,GAAA;OAA9E,MAAK;OAAmD,UAAUD,EAAAuD,CAAA;MAAYnD,GAAAA,MAAAA,GAAAA,CAAAA,UAAAA,CAAAA,GAAAA,EAAA,MACpFL,EAAGkC,EAAA,MAAQ,qBAAqBjC,EAAA6B,CAAA,CAAC,CAAA,oBAAA,CAAA,GAAA,KAAA,CAAA,GAAA,CAAA,CAAA,CAAA"}
package/dist/themes.css CHANGED
@@ -1,3 +1,5 @@
1
+ @import './components.css';
2
+
1
3
  /*
2
4
  * Alfakit themes. Shared by every renderer and imported by their `styles.css`.
3
5
  *
@@ -1004,337 +1006,3 @@
1004
1006
  box-shadow: none;
1005
1007
  outline: none;
1006
1008
  }
1007
-
1008
- /* ------------------------------------------------------------------ Charts */
1009
-
1010
- /*
1011
- * Chart.js paints axes, legends and tooltips on the canvas, so chart widgets read these
1012
- * properties from <html> (re-read when the theme or dark mode changes). Colours take any
1013
- * CSS colour; the widths and radius are unitless numbers. Override them in a theme:
1014
- * :root[data-alfakit-theme~='acme'] { --chart-tooltip-bg: oklch(0.2 0 0); }
1015
- * Stat sparklines (`[data-slot='stat-chart']`) use the `--stat-chart-*` properties.
1016
- */
1017
- :root {
1018
- --chart-text: var(--muted-foreground);
1019
- --chart-grid: var(--border);
1020
- --chart-legend-foreground: var(--muted-foreground);
1021
- --chart-tooltip-bg: var(--popover);
1022
- --chart-tooltip-foreground: var(--popover-foreground);
1023
- --chart-tooltip-border: var(--border);
1024
- --chart-tooltip-border-width: 1;
1025
- --chart-tooltip-radius: 6;
1026
- --stat-chart-stroke-width: 2;
1027
- --stat-chart-fill-opacity: 0.12;
1028
- }
1029
-
1030
- /*
1031
- * RichEditor `grid` column blocks and `lead` / `small` text, in the editor and in rendered
1032
- * content (`RichContentRenderer`). Columns stack on small screens. Stored as
1033
- * `<div data-type="grid" class="alfakit-grid alfakit-grid-cols-2"><div data-type="gridColumn">`
1034
- * and `<p class="alfakit-lead">`; copy these rules when showing content outside a panel.
1035
- */
1036
- :where(.alfakit-grid) {
1037
- display: grid;
1038
- gap: 1rem;
1039
- grid-template-columns: minmax(0, 1fr);
1040
- margin-block: 0.5rem;
1041
- }
1042
- :where(.alfakit-grid-column) {
1043
- min-width: 0;
1044
- }
1045
- :where(.alfakit-grid-column) > :first-child {
1046
- margin-block-start: 0;
1047
- }
1048
- @media (min-width: 768px) {
1049
- :where(.alfakit-grid-cols-2) {
1050
- grid-template-columns: repeat(2, minmax(0, 1fr));
1051
- }
1052
- :where(.alfakit-grid-cols-3) {
1053
- grid-template-columns: repeat(3, minmax(0, 1fr));
1054
- }
1055
- :where(.alfakit-grid-cols-4) {
1056
- grid-template-columns: repeat(4, minmax(0, 1fr));
1057
- }
1058
- :where(.alfakit-grid-cols-5) {
1059
- grid-template-columns: repeat(5, minmax(0, 1fr));
1060
- }
1061
- :where(.alfakit-grid-cols-6) {
1062
- grid-template-columns: repeat(6, minmax(0, 1fr));
1063
- }
1064
- }
1065
- :where([contenteditable] .alfakit-grid-column) {
1066
- border: 1px dashed var(--border);
1067
- border-radius: 0.375rem;
1068
- padding: 0.25rem 0.5rem;
1069
- }
1070
- :where(.alfakit-lead) {
1071
- font-size: 1.125em;
1072
- line-height: 1.6;
1073
- }
1074
- :where(.alfakit-prose small) {
1075
- font-size: 0.8125em;
1076
- }
1077
-
1078
- /* ---------------------------------------------------------- Calendar and tree */
1079
-
1080
- /*
1081
- * The calendar widget (alfasix/alfakit-calendar) draws FullCalendar inside
1082
- * `[data-slot="calendar"]`; FullCalendar reads these `--fc-*` variables, so every theme's
1083
- * tokens (and dark mode) apply. Override them on the slot to restyle one calendar.
1084
- */
1085
- :where(.fc[data-slot='calendar']) {
1086
- --fc-small-font-size: 0.75rem;
1087
- --fc-page-bg-color: var(--card);
1088
- --fc-neutral-bg-color: var(--muted);
1089
- --fc-neutral-text-color: var(--muted-foreground);
1090
- --fc-border-color: var(--border);
1091
- --fc-button-text-color: var(--foreground);
1092
- --fc-button-bg-color: var(--background);
1093
- --fc-button-border-color: var(--border);
1094
- --fc-button-hover-bg-color: var(--accent);
1095
- --fc-button-hover-border-color: var(--border);
1096
- --fc-button-active-bg-color: var(--secondary);
1097
- --fc-button-active-border-color: var(--border);
1098
- --fc-event-bg-color: var(--primary);
1099
- --fc-event-border-color: var(--primary);
1100
- --fc-event-text-color: var(--primary-foreground);
1101
- --fc-event-selected-overlay-color: color-mix(in oklab, var(--foreground) 25%, transparent);
1102
- --fc-more-link-bg-color: var(--muted);
1103
- --fc-more-link-text-color: var(--foreground);
1104
- --fc-non-business-color: color-mix(in oklab, var(--muted) 60%, transparent);
1105
- --fc-bg-event-color: var(--primary);
1106
- --fc-bg-event-opacity: 0.2;
1107
- --fc-highlight-color: color-mix(in oklab, var(--primary) 15%, transparent);
1108
- --fc-today-bg-color: color-mix(in oklab, var(--primary) 6%, transparent);
1109
- --fc-now-indicator-color: var(--destructive);
1110
- --fc-list-event-hover-bg-color: var(--accent);
1111
- color: var(--card-foreground);
1112
- }
1113
- /*
1114
- * FullCalendar puts its `fc` class on the slot element itself and injects its own CSS
1115
- * (`.fc .fc-button`, two classes), so these rules are plain selectors anchored on
1116
- * `.fc[data-slot='calendar']` (three) rather than `:where()`, which would always lose.
1117
- * Restyle one calendar with a more specific selector or with the `--fc-*` variables.
1118
- */
1119
- .fc[data-slot='calendar'] .fc-toolbar-title {
1120
- font-size: 1.125rem;
1121
- font-weight: 600;
1122
- line-height: 1.75rem;
1123
- color: var(--foreground);
1124
- }
1125
- .fc[data-slot='calendar'] .fc-button {
1126
- display: inline-flex;
1127
- align-items: center;
1128
- justify-content: center;
1129
- min-height: 2.25rem;
1130
- padding: 0.375rem 0.75rem;
1131
- border-radius: var(--radius);
1132
- font-size: 0.875rem;
1133
- font-weight: 500;
1134
- line-height: 1.25rem;
1135
- box-shadow: none;
1136
- text-transform: capitalize;
1137
- }
1138
- .fc[data-slot='calendar'] .fc-button .fc-icon {
1139
- font-size: 1.125rem;
1140
- }
1141
- .fc[data-slot='calendar'] .fc-button-group > .fc-button:not(:first-child) {
1142
- border-start-start-radius: 0;
1143
- border-end-start-radius: 0;
1144
- }
1145
- .fc[data-slot='calendar'] .fc-button-group > .fc-button:not(:last-child) {
1146
- border-start-end-radius: 0;
1147
- border-end-end-radius: 0;
1148
- }
1149
- .fc[data-slot='calendar'] .fc-button-primary:disabled {
1150
- opacity: 0.5;
1151
- }
1152
- .fc[data-slot='calendar'] .fc-button-primary:not(:disabled).fc-button-active,
1153
- .fc[data-slot='calendar'] .fc-button-primary:not(:disabled):active {
1154
- color: var(--secondary-foreground);
1155
- }
1156
- .fc[data-slot='calendar'] .fc-button-primary:focus,
1157
- .fc[data-slot='calendar'] .fc-button-primary:not(:disabled).fc-button-active:focus,
1158
- .fc[data-slot='calendar'] .fc-button-primary:not(:disabled):active:focus {
1159
- box-shadow: none;
1160
- }
1161
- .fc[data-slot='calendar'] .fc-button:focus-visible {
1162
- outline: 2px solid var(--ring);
1163
- outline-offset: 2px;
1164
- z-index: 2;
1165
- }
1166
- .fc[data-slot='calendar'] a {
1167
- color: inherit;
1168
- }
1169
- .fc[data-slot='calendar'] .fc-daygrid-day-number,
1170
- .fc[data-slot='calendar'] .fc-col-header-cell-cushion {
1171
- text-decoration: none;
1172
- }
1173
- .fc[data-slot='calendar'] .fc-col-header-cell-cushion {
1174
- padding-block: 0.375rem;
1175
- font-size: 0.75rem;
1176
- font-weight: 500;
1177
- color: var(--muted-foreground);
1178
- }
1179
- .fc[data-slot='calendar'] .fc-daygrid-day-number {
1180
- font-size: 0.875rem;
1181
- }
1182
- .fc[data-slot='calendar'] .fc-day-other .fc-daygrid-day-number {
1183
- color: var(--muted-foreground);
1184
- }
1185
- /* Today: a tinted cell (`--fc-today-bg-color`) and the date in a primary pill. */
1186
- .fc[data-slot='calendar'] .fc-daygrid-day.fc-day-today .fc-daygrid-day-number {
1187
- display: inline-flex;
1188
- align-items: center;
1189
- justify-content: center;
1190
- min-width: 1.75rem;
1191
- height: 1.75rem;
1192
- margin: 0.25rem;
1193
- padding: 0 0.375rem;
1194
- border-radius: 9999px;
1195
- background: var(--primary);
1196
- color: var(--primary-foreground);
1197
- font-weight: 600;
1198
- }
1199
- .fc[data-slot='calendar'] .fc-col-header-cell.fc-day-today .fc-col-header-cell-cushion {
1200
- color: var(--primary);
1201
- font-weight: 600;
1202
- }
1203
- .fc[data-slot='calendar'] .fc-event {
1204
- border-radius: min(var(--radius), 0.375rem);
1205
- }
1206
- .fc[data-slot='calendar'] .fc-daygrid-event,
1207
- .fc[data-slot='calendar'] .fc-timegrid-event .fc-event-main,
1208
- .fc[data-slot='calendar'] .fc-list-event td {
1209
- font-size: 0.75rem;
1210
- }
1211
- .fc[data-slot='calendar'] .fc-daygrid-dot-event:hover,
1212
- .fc[data-slot='calendar'] .fc-daygrid-dot-event.fc-event-mirror {
1213
- background: var(--accent);
1214
- }
1215
- .fc[data-slot='calendar'] .fc-list-day-cushion,
1216
- .fc[data-slot='calendar'] .fc-popover-header {
1217
- color: var(--foreground);
1218
- }
1219
- .fc[data-slot='calendar'] .fc-popover {
1220
- border-radius: var(--radius);
1221
- box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
1222
- overflow: hidden;
1223
- }
1224
- .fc[data-slot='calendar'] .fc-timegrid-slot-label,
1225
- .fc[data-slot='calendar'] .fc-timegrid-axis,
1226
- .fc[data-slot='calendar'] .fc-list-event-time {
1227
- color: var(--muted-foreground);
1228
- font-size: 0.75rem;
1229
- }
1230
- /*
1231
- * The list view hides its column headers for screen readers with `left: -10000px`. Right to
1232
- * left that is scrollable overflow: the whole page gains a 10 000 px horizontal scroll and the
1233
- * top bar slides under the sidebar. Clip it in place instead (still read by screen readers).
1234
- */
1235
- .fc[data-slot='calendar'] .fc-list-table thead {
1236
- left: auto;
1237
- inset-inline-start: 0;
1238
- width: 1px;
1239
- height: 1px;
1240
- overflow: hidden;
1241
- clip-path: inset(50%);
1242
- white-space: nowrap;
1243
- }
1244
-
1245
- /*
1246
- * Fields contain what they position. Headless switches, checkboxes and radios render a
1247
- * visually hidden native input beside the control, absolutely positioned (and shifted by
1248
- * -100%); without a positioned field it lands at the page edge and, right to left, widens
1249
- * the page on phones.
1250
- */
1251
- :where([data-slot='field']) {
1252
- position: relative;
1253
- }
1254
-
1255
- /*
1256
- * Narrow screens: FullCalendar keeps its header toolbar on one row, wider than a phone.
1257
- * Its chunks (navigation, title, views) wrap instead, and the title shrinks. Flex gaps and
1258
- * `justify-content` follow the writing direction, so this works right to left too. (Plain
1259
- * selectors: FullCalendar injects its own CSS, which would beat `:where()`; the slot is
1260
- * the `.fc` element itself.)
1261
- */
1262
- @media (max-width: 39.99rem) {
1263
- [data-slot='calendar'] .fc-toolbar.fc-header-toolbar {
1264
- flex-wrap: wrap;
1265
- gap: 0.5rem;
1266
- }
1267
- [data-slot='calendar'] .fc-toolbar .fc-toolbar-chunk {
1268
- display: flex;
1269
- flex-wrap: wrap;
1270
- align-items: center;
1271
- gap: 0.25rem;
1272
- min-width: 0;
1273
- }
1274
- [data-slot='calendar'] .fc-toolbar .fc-toolbar-title {
1275
- font-size: 1rem;
1276
- overflow-wrap: anywhere;
1277
- }
1278
- [data-slot='calendar'] .fc-toolbar .fc-button {
1279
- font-size: 0.8125rem;
1280
- }
1281
- }
1282
-
1283
- /*
1284
- * The tree (alfasix/alfakit-tree): the drop indicator while dragging. Rows carry
1285
- * `data-drop="before|after|inside"`; lines are drawn above or below the row, so they
1286
- * need no direction.
1287
- */
1288
- :where([data-slot='tree-item'][data-drop='before']) {
1289
- box-shadow: inset 0 2px 0 0 var(--primary);
1290
- }
1291
- :where([data-slot='tree-item'][data-drop='after']) {
1292
- box-shadow: inset 0 -2px 0 0 var(--primary);
1293
- }
1294
- :where([data-slot='tree-item'][data-drop='inside']) {
1295
- background-color: color-mix(in oklab, var(--primary) 10%, transparent);
1296
- outline: 1px dashed var(--primary);
1297
- outline-offset: -1px;
1298
- }
1299
-
1300
- /*
1301
- * The Kanban board (alfasix/alfakit-kanban). A card being dragged leaves a dashed
1302
- * placeholder (`data-picked="pointer"`) while a copy follows the pointer
1303
- * (`data-slot="kanban-ghost"`); a card picked up with the keyboard is lifted
1304
- * (`data-picked="keyboard"`). A list the picked card may not enter has `data-refused`.
1305
- */
1306
- :where([data-slot='kanban-card'][data-picked='pointer']) {
1307
- opacity: 0.45;
1308
- }
1309
- :where([data-slot='kanban-card'][data-picked='pointer'] > [data-slot='kanban-card-body']) {
1310
- border-style: dashed;
1311
- box-shadow: none;
1312
- }
1313
- :where([data-slot='kanban-card'][data-picked='keyboard'] > [data-slot='kanban-card-body']) {
1314
- outline: 2px solid var(--primary);
1315
- outline-offset: 2px;
1316
- box-shadow: 0 10px 24px -12px color-mix(in oklab, var(--foreground) 45%, transparent);
1317
- }
1318
- :where([data-slot='kanban-card'][data-saving]) {
1319
- opacity: 0.7;
1320
- }
1321
- :where([data-slot='kanban-ghost']) {
1322
- cursor: grabbing;
1323
- list-style: none;
1324
- box-shadow: 0 18px 40px -16px color-mix(in oklab, var(--foreground) 55%, transparent);
1325
- }
1326
- :where([data-slot='kanban-dropzone'][data-refused]) {
1327
- background-color: color-mix(in oklab, var(--destructive) 8%, transparent);
1328
- outline: 1px dashed var(--destructive);
1329
- outline-offset: -1px;
1330
- }
1331
- :where(body[data-kanban-dragging]) {
1332
- cursor: grabbing;
1333
- user-select: none;
1334
- -webkit-user-select: none;
1335
- }
1336
- @media (prefers-reduced-motion: reduce) {
1337
- :where([data-slot='kanban-card'] > [data-slot='kanban-card-body']) {
1338
- transition: none;
1339
- }
1340
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfakit/vue",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Vue 3 + shadcn-vue renderer for Alfakit, the Laravel admin panel builder by Alfa Six.",
5
5
  "license": "MIT",
6
6
  "author": "Alfa Six (https://alfasixbh.com)",
@@ -96,7 +96,7 @@
96
96
  "reka-ui": "^2.11.0",
97
97
  "tailwind-merge": "^3.7.0",
98
98
  "vue-sonner": "^2.0.9",
99
- "@alfakit/core": "0.1.0"
99
+ "@alfakit/core": "0.1.2"
100
100
  },
101
101
  "peerDependencies": {
102
102
  "@inertiajs/vue3": "^3.0.0",
@@ -119,7 +119,7 @@
119
119
  "provenance": true
120
120
  },
121
121
  "scripts": {
122
- "build": "vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/styles.css dist/styles.css && cp ../core/themes.css dist/themes.css && cp ../core/standalone.css dist/standalone.css && node ../../scripts/eject-manifest.mjs .",
122
+ "build": "vite build && vue-tsc --declaration --emitDeclarationOnly -p tsconfig.build.json && cp src/styles.css dist/styles.css && cp ../core/themes.css dist/themes.css && cp ../core/components.css dist/components.css && cp ../core/standalone.css dist/standalone.css && node ../../scripts/eject-manifest.mjs .",
123
123
  "dev": "vite build --watch",
124
124
  "typecheck": "vue-tsc --noEmit",
125
125
  "test": "vitest run"
@@ -4,6 +4,8 @@ import {
4
4
  bindsKeyBindings,
5
5
  formatKeyBinding,
6
6
  iconButtonSize,
7
+ isActionLoading,
8
+ isActionProcessing,
7
9
  registerKeyBindings,
8
10
  resolveActionSize,
9
11
  } from '@alfakit/core'
@@ -47,9 +49,12 @@ const props = withDefaults(defineProps<ActionButtonProps>(), {
47
49
  })
48
50
 
49
51
  const runner = useActionRunner()
50
- const loading = useStoreSelector(runner.store, (state) => state.loading === props.action.name)
52
+ // Only this run (this record's button), not the same action in every table row.
53
+ const loading = useStoreSelector(runner.store, (state) =>
54
+ isActionLoading(state, props.action, props.context),
55
+ )
51
56
  const processing = useStoreSelector(runner.store, (state) =>
52
- state.modals.some((modal) => modal.action.name === props.action.name && modal.processing),
57
+ isActionProcessing(state, props.action, props.context),
53
58
  )
54
59
 
55
60
  const variant = computed(
@@ -87,7 +92,7 @@ function buttonClasses(action: ActionSchema, kind: ActionSchema['variant']): str
87
92
  return colorClass(ghostButtonColorClasses, color, 'gray')
88
93
  case 'link':
89
94
  return cn(
90
- 'h-auto p-0 underline-offset-4 hover:underline',
95
+ 'h-auto p-0 underline-offset-4 hover:underline has-[>svg]:px-0',
91
96
  colorClass(textColorClasses, color, 'primary'),
92
97
  )
93
98
  case 'icon-button':
@@ -278,9 +283,12 @@ const disabledTooltip = computed(() => Boolean(props.action.disabled && tooltip.
278
283
  </TooltipTrigger>
279
284
  <TooltipContent>
280
285
  {{ tooltip }}
281
- <kbd v-if="shortcut" class="ms-2 rounded border border-white/20 px-1 font-mono text-[10px]">{{
282
- formatKeyBinding(shortcut)
283
- }}</kbd>
286
+ <kbd
287
+ v-if="shortcut"
288
+ dir="ltr"
289
+ class="ms-2 rounded border border-white/20 px-1 font-mono text-[10px]"
290
+ >{{ formatKeyBinding(shortcut) }}</kbd
291
+ >
284
292
  </TooltipContent>
285
293
  </Tooltip>
286
294
  <template v-else>
@@ -2,6 +2,7 @@
2
2
  import type { OpenModal } from '@alfakit/core'
3
3
  import {
4
4
  actionFormComponent,
5
+ formIdPrefix,
5
6
  actionFormParams,
6
7
  confirmModalClose,
7
8
  FormStore,
@@ -103,6 +104,8 @@ const form = (() => {
103
104
  return new FormStore(schema.value.form, {
104
105
  token: context.token,
105
106
  component: actionFormComponent(action, context),
107
+ // Own field ids: the modal opens over a form whose fields may share names.
108
+ idPrefix: formIdPrefix(actionFormComponent(action, context)),
106
109
  record: context.record ?? null,
107
110
  refreshUrl: panel.value.endpoints.schemaRefresh,
108
111
  optionsUrl: panel.value.endpoints.schemaOptions,
@@ -513,7 +516,6 @@ const hasBody = computed(() =>
513
516
  </Button>
514
517
  </div>
515
518
  </DialogFooter>
516
- <span class="sr-only">{{ t('close', {}, 'Close') }}</span>
517
519
  </DialogContent>
518
520
  </Dialog>
519
521
  </template>
@@ -45,6 +45,7 @@ const onAlpha = (event: Event) =>
45
45
  <Input
46
46
  :id="id"
47
47
  :name="props.component.name"
48
+ dir="ltr"
48
49
  :model-value="value ?? ''"
49
50
  :placeholder="props.component.placeholder ?? (isHex ? '#000000' : props.component.format)"
50
51
  :disabled="disabled"
@@ -210,7 +210,7 @@ const removeTag = (event: Event, key: string) => {
210
210
  )
211
211
  "
212
212
  >
213
- <span class="flex flex-1 flex-wrap items-center gap-1 text-start">
213
+ <span class="flex min-w-0 flex-1 flex-wrap items-center gap-1 text-start">
214
214
  <span v-if="selected.length === 0" class="text-muted-foreground">{{
215
215
  props.component.placeholder ?? t('select_option', {}, 'Select an option')
216
216
  }}</span>
@@ -22,7 +22,7 @@ import {
22
22
  fileUploadAccept,
23
23
  filesFromClipboard,
24
24
  fileUploadPaths,
25
- formatBytes,
25
+ fileManagerSize,
26
26
  insertUploadedFile,
27
27
  moveRepeaterItem,
28
28
  requestJson,
@@ -43,7 +43,7 @@ import {
43
43
  } from '@lucide/vue'
44
44
  import { computed, ref, shallowRef, watch } from 'vue'
45
45
  import { useStore } from '../../composables/use-store'
46
- import { useChoice, usePanel, useT } from '../../context'
46
+ import { useChoice, useFormatter, usePanel, useT } from '../../context'
47
47
  import { cn } from '../../lib/utils'
48
48
  import { useField, useFormStore } from '../form/form-context'
49
49
  import FieldWrapper from '../schema/FieldWrapper.vue'
@@ -59,6 +59,7 @@ interface LocalFile extends UploadedFile {
59
59
 
60
60
  const props = defineProps<{ component: FileUploadSchema }>()
61
61
  const t = useT()
62
+ const formatter = useFormatter()
62
63
  const choice = useChoice()
63
64
  const panel = usePanel()
64
65
  const {
@@ -424,7 +425,9 @@ const onItemDrop = (event: DragEvent, index: number) => {
424
425
  const hints = computed(() =>
425
426
  [
426
427
  props.component.acceptedFileTypes?.join(', '),
427
- props.component.maxSize ? `≤ ${formatBytes(props.component.maxSize * 1024, 0)}` : null,
428
+ props.component.maxSize
429
+ ? `≤ ${fileManagerSize(props.component.maxSize * 1024, formatter.value)}`
430
+ : null,
428
431
  props.component.minFiles
429
432
  ? choice(
430
433
  'form.min_files',
@@ -491,7 +494,7 @@ function cssLength(value: number | string): string {
491
494
  type="button"
492
495
  variant="ghost"
493
496
  size="icon-xs"
494
- :aria-label="t('remove', {}, 'Remove')"
497
+ :aria-label="t('file_upload.remove', { name: file.name }, 'Remove :name')"
495
498
  @click="removeEntry(file)"
496
499
  ><XIcon
497
500
  /></Button>
@@ -525,7 +528,7 @@ function cssLength(value: number | string): string {
525
528
  : file.progress !== undefined && !file.error
526
529
  ? (props.component.uploadingMessage ?? t('form.uploading', {}, 'Uploading…'))
527
530
  : file.size
528
- ? formatBytes(file.size)
531
+ ? fileManagerSize(file.size, formatter)
529
532
  : file.temporary
530
533
  ? t('form.uploading', {}, 'Pending')
531
534
  : '')
@@ -541,7 +544,7 @@ function cssLength(value: number | string): string {
541
544
  type="button"
542
545
  variant="ghost"
543
546
  size="icon-xs"
544
- :aria-label="t('form.move_up', {}, 'Move up')"
547
+ :aria-label="t('file_upload.move_up', { name: file.name }, 'Move :name up')"
545
548
  :disabled="index === 0"
546
549
  @click="move(index, index - 1)"
547
550
  ><ChevronUpIcon
@@ -550,7 +553,7 @@ function cssLength(value: number | string): string {
550
553
  type="button"
551
554
  variant="ghost"
552
555
  size="icon-xs"
553
- :aria-label="t('form.move_down', {}, 'Move down')"
556
+ :aria-label="t('file_upload.move_down', { name: file.name }, 'Move :name down')"
554
557
  :disabled="index === files.length - 1"
555
558
  @click="move(index, index + 1)"
556
559
  ><ChevronDownIcon
@@ -562,7 +565,7 @@ function cssLength(value: number | string): string {
562
565
  :variant="circle ? 'secondary' : 'ghost'"
563
566
  size="icon-xs"
564
567
  :class="cn(circle && 'rounded-full shadow')"
565
- :aria-label="t('image_editor.title', {}, 'Edit image')"
568
+ :aria-label="t('file_upload.edit', { name: file.name }, 'Edit :name')"
566
569
  :title="t('image_editor.title', {}, 'Edit image')"
567
570
  data-action="edit-image"
568
571
  @click="void editExisting(file)"
@@ -579,7 +582,7 @@ function cssLength(value: number | string): string {
579
582
  :href="uploadedFileLinks(file).open"
580
583
  target="_blank"
581
584
  rel="noopener noreferrer"
582
- :aria-label="`${t('open', {}, 'Open')} ${t('opens_in_new_tab', {}, '(opens in a new tab)')}`"
585
+ :aria-label="`${t('file_upload.open', { name: file.name }, 'Open :name')} ${t('opens_in_new_tab', {}, '(opens in a new tab)')}`"
583
586
  ><ExternalLinkIcon
584
587
  /></a>
585
588
  </Button>
@@ -593,7 +596,7 @@ function cssLength(value: number | string): string {
593
596
  <a
594
597
  :href="uploadedFileLinks(file).download"
595
598
  download
596
- :aria-label="t('download', {}, 'Download')"
599
+ :aria-label="t('file_upload.download', { name: file.name }, 'Download :name')"
597
600
  ><DownloadIcon
598
601
  /></a>
599
602
  </Button>
@@ -603,7 +606,7 @@ function cssLength(value: number | string): string {
603
606
  :variant="circle ? 'secondary' : 'ghost'"
604
607
  size="icon-xs"
605
608
  :class="cn(circle && 'rounded-full shadow')"
606
- :aria-label="t('remove', {}, 'Remove')"
609
+ :aria-label="t('file_upload.remove', { name: file.name }, 'Remove :name')"
607
610
  @click="removeEntry(file)"
608
611
  ><XIcon
609
612
  /></Button>
@@ -43,7 +43,6 @@ const onInput = (event: Event) => {
43
43
  inputmode="numeric"
44
44
  autocomplete="one-time-code"
45
45
  pattern="[0-9]*"
46
- :maxlength="props.component.length"
47
46
  :model-value="value ?? ''"
48
47
  :placeholder="props.component.placeholder"
49
48
  :disabled="disabled"
@@ -54,6 +53,7 @@ const onInput = (event: Event) => {
54
53
  :aria-describedby="aria['aria-describedby']"
55
54
  :aria-required="aria['aria-required']"
56
55
  data-slot="one-time-code-input"
56
+ data-input=""
57
57
  class="max-w-56 text-center font-mono text-lg tracking-[0.5em] tabular-nums"
58
58
  v-bind="props.component.extraInputAttributes"
59
59
  @input="onInput"
@@ -62,7 +62,7 @@ const plainLabel = (label: string): string =>
62
62
  @blur="blur"
63
63
  >
64
64
  <option v-if="props.component.selectablePlaceholder" value="">
65
- {{ props.component.placeholder ?? '' }}
65
+ {{ props.component.placeholder ?? t('select_option', {}, 'Select an option') }}
66
66
  </option>
67
67
  <template
68
68
  v-for="option in props.component.options"
@@ -97,7 +97,9 @@ const plainLabel = (label: string): string =>
97
97
  :aria-readonly="readOnly || undefined"
98
98
  class="w-full"
99
99
  >
100
- <SelectValue :placeholder="props.component.placeholder ?? ''" />
100
+ <SelectValue
101
+ :placeholder="props.component.placeholder ?? t('select_option', {}, 'Select an option')"
102
+ />
101
103
  </SelectTrigger>
102
104
  <SelectContent>
103
105
  <SelectItem