@wrrdev/fenix-ui 1.1.8 → 1.1.10

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 (50) hide show
  1. package/README.md +2 -2
  2. package/dist/components/drawer/drawer.d.ts.map +1 -1
  3. package/dist/components/drawer/drawer.js +4 -0
  4. package/dist/components/drawer/drawer.js.map +1 -1
  5. package/dist/components/pagination/pagination.d.ts +1 -0
  6. package/dist/components/pagination/pagination.d.ts.map +1 -1
  7. package/dist/components/pagination/pagination.js +18 -2
  8. package/dist/components/pagination/pagination.js.map +1 -1
  9. package/dist/components/table/table.d.ts +60 -4
  10. package/dist/components/table/table.d.ts.map +1 -1
  11. package/dist/components/table/table.js +96 -18
  12. package/dist/components/table/table.js.map +1 -1
  13. package/dist/components/toast/toast.d.ts +46 -1
  14. package/dist/components/toast/toast.d.ts.map +1 -1
  15. package/dist/components/toast/toast.js +128 -5
  16. package/dist/components/toast/toast.js.map +1 -1
  17. package/dist/core/jsx.d.ts +84 -1
  18. package/dist/core/jsx.d.ts.map +1 -1
  19. package/dist/core/jsx.js.map +1 -1
  20. package/dist/core/vue.d.ts +7 -1
  21. package/dist/core/vue.d.ts.map +1 -1
  22. package/dist/core/vue.js.map +1 -1
  23. package/dist/docs/app.d.ts +2 -6
  24. package/dist/docs/app.d.ts.map +1 -1
  25. package/dist/docs/componentes/table-cell-rules.d.ts +3 -0
  26. package/dist/docs/componentes/table-cell-rules.d.ts.map +1 -0
  27. package/dist/docs/componentes/table.doc.d.ts.map +1 -1
  28. package/dist/docs/componentes/toast.doc.d.ts.map +1 -1
  29. package/dist/docs/router.d.ts +17 -0
  30. package/dist/docs/router.d.ts.map +1 -0
  31. package/dist/docs/shell.d.ts +43 -0
  32. package/dist/docs/shell.d.ts.map +1 -0
  33. package/dist/docs/types.d.ts +9 -0
  34. package/dist/docs/types.d.ts.map +1 -1
  35. package/dist/docs/ui/code.d.ts +12 -0
  36. package/dist/docs/ui/code.d.ts.map +1 -0
  37. package/dist/docs/ui/kit.d.ts +18 -0
  38. package/dist/docs/ui/kit.d.ts.map +1 -0
  39. package/dist/docs/ui/tabs.d.ts +23 -0
  40. package/dist/docs/ui/tabs.d.ts.map +1 -0
  41. package/dist/fenix-ui.umd.min.js +179 -116
  42. package/dist/fenix-ui2.esm.js.map +1 -1
  43. package/dist/fenix-ui4.esm.js +243 -26
  44. package/dist/fenix-ui4.esm.js.map +1 -1
  45. package/dist/fenix-ui5.esm.js +4 -1
  46. package/dist/fenix-ui5.esm.js.map +1 -1
  47. package/dist/plugins/auto-import.d.ts.map +1 -1
  48. package/dist/plugins/auto-import.js +4 -1
  49. package/dist/plugins/auto-import.js.map +1 -1
  50. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"fenix-ui2.esm.js","sources":["../src/core/vue.ts"],"sourcesContent":["/**\n * Tipagem de componentes <fx-*> para Vue 3 (Volar / vue-tsc).\n *\n * Este módulo é OPT-IN: importe `@wrrdev/fenix-ui/vue` uma única vez\n * (ex.: no `main.ts`) para habilitar autocomplete + validação de atributos\n * dos elementos `fx-*` nos templates SFC.\n *\n * - `IntrinsicElementAttributes` (Vue 3.5+): ponto oficial de extensão para\n * elementos nativos/custom — alimenta `NativeElements` e o\n * `JSX.IntrinsicElements` usado pelo Volar para tags com hífen.\n * - `GlobalComponents`: registro adicional como componentes globais.\n */\nimport type {\n FxAutocompleteProps,\n FxAccordionPanelProps,\n FxAccordionProps,\n FxAlertProps,\n FxAvatarProps,\n FxBadgeProps,\n FxBreadcrumbProps,\n FxButtonProps,\n FxCalendarProps,\n FxCardProps,\n FxCarouselProps,\n FxCheckboxProps,\n FxChipProps,\n FxConfirmPopupProps,\n FxDatepickerProps,\n FxDialogProps,\n FxDropdownItemProps,\n FxDropdownProps,\n FxDrawerProps,\n FxEmptyStateProps,\n FxFileUploadProps,\n FxFloatlabelProps,\n FxIconProps,\n FxInputProps,\n FxKnobProps,\n FxMenuProps,\n FxMultiselectProps,\n FxOrderListProps,\n FxPaginationProps,\n FxPasswordStrengthProps,\n FxPickListProps,\n FxPopoverProps,\n FxProgressProps,\n FxRadioProps,\n FxRatingProps,\n FxSelectProps,\n FxSkeletonProps,\n FxSliderProps,\n FxSpinnerProps,\n FxStepperProps,\n FxSwitchProps,\n FxTableProps,\n FxTabPanelProps,\n FxTabsProps,\n FxTextareaProps,\n FxTimelineProps,\n FxToastProps,\n FxToggleButtonGroupProps,\n FxTooltipProps,\n FxTreeProps,\n} from './jsx';\n\nimport type {} from '@vue/runtime-dom';\n\ntype FxComp<P> = import('vue').FunctionalComponent<P>;\n\ndeclare module '@vue/runtime-core' {\n interface GlobalComponents {\n 'fx-button': FxComp<FxButtonProps>;\n 'fx-badge': FxComp<FxBadgeProps>;\n 'fx-spinner': FxComp<FxSpinnerProps>;\n 'fx-input': FxComp<FxInputProps>;\n 'fx-select': FxComp<FxSelectProps>;\n 'fx-switch': FxComp<FxSwitchProps>;\n 'fx-checkbox': FxComp<FxCheckboxProps>;\n 'fx-radio': FxComp<FxRadioProps>;\n 'fx-textarea': FxComp<FxTextareaProps>;\n 'fx-multiselect': FxComp<FxMultiselectProps>;\n 'fx-calendar': FxComp<FxCalendarProps>;\n 'fx-datepicker': FxComp<FxDatepickerProps>;\n 'fx-table': FxComp<FxTableProps>;\n 'fx-floatlabel': FxComp<FxFloatlabelProps>;\n 'fx-dialog': FxComp<FxDialogProps>;\n 'fx-drawer': FxComp<FxDrawerProps>;\n 'fx-toast': FxComp<FxToastProps>;\n 'fx-tooltip': FxComp<FxTooltipProps>;\n 'fx-tabs': FxComp<FxTabsProps>;\n 'fx-tab-panel': FxComp<FxTabPanelProps>;\n 'fx-progress': FxComp<FxProgressProps>;\n 'fx-skeleton': FxComp<FxSkeletonProps>;\n 'fx-alert': FxComp<FxAlertProps>;\n 'fx-dropdown': FxComp<FxDropdownProps>;\n 'fx-dropdown-item': FxComp<FxDropdownItemProps>;\n 'fx-pagination': FxComp<FxPaginationProps>;\n 'fx-autocomplete': FxComp<FxAutocompleteProps>;\n 'fx-fileupload': FxComp<FxFileUploadProps>;\n 'fx-slider': FxComp<FxSliderProps>;\n 'fx-chip': FxComp<FxChipProps>;\n 'fx-avatar': FxComp<FxAvatarProps>;\n 'fx-icon': FxComp<FxIconProps>;\n 'fx-card': FxComp<FxCardProps>;\n 'fx-breadcrumb': FxComp<FxBreadcrumbProps>;\n 'fx-popover': FxComp<FxPopoverProps>;\n 'fx-stepper': FxComp<FxStepperProps>;\n 'fx-rating': FxComp<FxRatingProps>;\n 'fx-menu': FxComp<FxMenuProps>;\n 'fx-toggle-button-group': FxComp<FxToggleButtonGroupProps>;\n 'fx-empty-state': FxComp<FxEmptyStateProps>;\n 'fx-password-strength': FxComp<FxPasswordStrengthProps>;\n 'fx-timeline': FxComp<FxTimelineProps>;\n 'fx-carousel': FxComp<FxCarouselProps>;\n 'fx-tree': FxComp<FxTreeProps>;\n 'fx-confirmpopup': FxComp<FxConfirmPopupProps>;\n 'fx-knob': FxComp<FxKnobProps>;\n 'fx-accordion': FxComp<FxAccordionProps>;\n 'fx-accordion-panel': FxComp<FxAccordionPanelProps>;\n 'fx-orderlist': FxComp<FxOrderListProps>;\n 'fx-picklist': FxComp<FxPickListProps>;\n }\n}\n\ndeclare module '@vue/runtime-dom' {\n interface IntrinsicElementAttributes {\n 'fx-button': FxButtonProps;\n 'fx-badge': FxBadgeProps;\n 'fx-spinner': FxSpinnerProps;\n 'fx-input': FxInputProps;\n 'fx-select': FxSelectProps;\n 'fx-switch': FxSwitchProps;\n 'fx-checkbox': FxCheckboxProps;\n 'fx-radio': FxRadioProps;\n 'fx-textarea': FxTextareaProps;\n 'fx-multiselect': FxMultiselectProps;\n 'fx-calendar': FxCalendarProps;\n 'fx-datepicker': FxDatepickerProps;\n 'fx-table': FxTableProps;\n 'fx-floatlabel': FxFloatlabelProps;\n 'fx-dialog': FxDialogProps;\n 'fx-drawer': FxDrawerProps;\n 'fx-toast': FxToastProps;\n 'fx-tooltip': FxTooltipProps;\n 'fx-tabs': FxTabsProps;\n 'fx-tab-panel': FxTabPanelProps;\n 'fx-progress': FxProgressProps;\n 'fx-skeleton': FxSkeletonProps;\n 'fx-alert': FxAlertProps;\n 'fx-dropdown': FxDropdownProps;\n 'fx-dropdown-item': FxDropdownItemProps;\n 'fx-pagination': FxPaginationProps;\n 'fx-autocomplete': FxAutocompleteProps;\n 'fx-fileupload': FxFileUploadProps;\n 'fx-slider': FxSliderProps;\n 'fx-chip': FxChipProps;\n 'fx-avatar': FxAvatarProps;\n 'fx-icon': FxIconProps;\n 'fx-card': FxCardProps;\n 'fx-breadcrumb': FxBreadcrumbProps;\n 'fx-popover': FxPopoverProps;\n 'fx-stepper': FxStepperProps;\n 'fx-rating': FxRatingProps;\n 'fx-menu': FxMenuProps;\n 'fx-toggle-button-group': FxToggleButtonGroupProps;\n 'fx-empty-state': FxEmptyStateProps;\n 'fx-password-strength': FxPasswordStrengthProps;\n 'fx-timeline': FxTimelineProps;\n 'fx-carousel': FxCarouselProps;\n 'fx-tree': FxTreeProps;\n 'fx-confirmpopup': FxConfirmPopupProps;\n 'fx-knob': FxKnobProps;\n 'fx-accordion': FxAccordionProps;\n 'fx-accordion-panel': FxAccordionPanelProps;\n 'fx-orderlist': FxOrderListProps;\n 'fx-picklist': FxPickListProps;\n }\n}\n\n/** Marcador para `import '@wrrdev/fenix-ui/vue'` funcionar como side-effect import. */\nexport const FX_VUE_TYPES = true as const;\n\n/** Reexporta os tipos nomeados de props para consumidores Vue. */\nexport type * from './jsx';\n\n"],"names":[],"mappings":"AAoLO,MAAM,eAAe;"}
1
+ {"version":3,"file":"fenix-ui2.esm.js","sources":["../src/core/vue.ts"],"sourcesContent":["/**\n * Tipagem de componentes <fx-*> para Vue 3 (Volar / vue-tsc).\n *\n * Este módulo é OPT-IN: importe `@wrrdev/fenix-ui/vue` uma única vez\n * (ex.: no `main.ts`) para habilitar autocomplete + validação de atributos\n * dos elementos `fx-*` nos templates SFC.\n *\n * - `IntrinsicElementAttributes` (Vue 3.5+): ponto oficial de extensão para\n * elementos nativos/custom — alimenta `NativeElements` e o\n * `JSX.IntrinsicElements` usado pelo Volar para tags com hífen.\n * - `GlobalComponents`: registro adicional como componentes globais.\n */\nimport type {\n FxAutocompleteProps,\n FxAccordionPanelProps,\n FxAccordionProps,\n FxAlertProps,\n FxAvatarProps,\n FxBadgeProps,\n FxBreadcrumbProps,\n FxButtonProps,\n FxCalendarProps,\n FxCardProps,\n FxCarouselProps,\n FxCellProps,\n FxCheckboxProps,\n FxChipProps,\n FxColumnProps,\n FxConfirmPopupProps,\n FxDatepickerProps,\n FxDialogProps,\n FxDropdownItemProps,\n FxDropdownProps,\n FxDrawerProps,\n FxEmptyStateProps,\n FxFileUploadProps,\n FxFloatlabelProps,\n FxIconProps,\n FxInputProps,\n FxKnobProps,\n FxMenuProps,\n FxMultiselectProps,\n FxOrderListProps,\n FxPaginationProps,\n FxPasswordStrengthProps,\n FxPickListProps,\n FxPopoverProps,\n FxProgressProps,\n FxRadioProps,\n FxRatingProps,\n FxSelectProps,\n FxSkeletonProps,\n FxSliderProps,\n FxSpinnerProps,\n FxStepperProps,\n FxSwitchProps,\n FxTableProps,\n FxTabPanelProps,\n FxTabsProps,\n FxTextareaProps,\n FxTimelineProps,\n FxToastProps,\n FxToggleButtonGroupProps,\n FxToolbarProps,\n FxTooltipProps,\n FxTreeProps,\n} from './jsx';\n\nimport type {} from '@vue/runtime-dom';\n\ntype FxComp<P> = import('vue').FunctionalComponent<P>;\n\ndeclare module '@vue/runtime-core' {\n interface GlobalComponents {\n 'fx-button': FxComp<FxButtonProps>;\n 'fx-badge': FxComp<FxBadgeProps>;\n 'fx-spinner': FxComp<FxSpinnerProps>;\n 'fx-input': FxComp<FxInputProps>;\n 'fx-select': FxComp<FxSelectProps>;\n 'fx-switch': FxComp<FxSwitchProps>;\n 'fx-checkbox': FxComp<FxCheckboxProps>;\n 'fx-radio': FxComp<FxRadioProps>;\n 'fx-textarea': FxComp<FxTextareaProps>;\n 'fx-multiselect': FxComp<FxMultiselectProps>;\n 'fx-calendar': FxComp<FxCalendarProps>;\n 'fx-datepicker': FxComp<FxDatepickerProps>;\n 'fx-table': FxComp<FxTableProps>;\n 'fx-column': FxComp<FxColumnProps>;\n 'fx-cell': FxComp<FxCellProps>;\n 'fx-toolbar': FxComp<FxToolbarProps>;\n 'fx-floatlabel': FxComp<FxFloatlabelProps>;\n 'fx-dialog': FxComp<FxDialogProps>;\n 'fx-drawer': FxComp<FxDrawerProps>;\n 'fx-toast': FxComp<FxToastProps>;\n 'fx-tooltip': FxComp<FxTooltipProps>;\n 'fx-tabs': FxComp<FxTabsProps>;\n 'fx-tab-panel': FxComp<FxTabPanelProps>;\n 'fx-progress': FxComp<FxProgressProps>;\n 'fx-skeleton': FxComp<FxSkeletonProps>;\n 'fx-alert': FxComp<FxAlertProps>;\n 'fx-dropdown': FxComp<FxDropdownProps>;\n 'fx-dropdown-item': FxComp<FxDropdownItemProps>;\n 'fx-pagination': FxComp<FxPaginationProps>;\n 'fx-autocomplete': FxComp<FxAutocompleteProps>;\n 'fx-fileupload': FxComp<FxFileUploadProps>;\n 'fx-slider': FxComp<FxSliderProps>;\n 'fx-chip': FxComp<FxChipProps>;\n 'fx-avatar': FxComp<FxAvatarProps>;\n 'fx-icon': FxComp<FxIconProps>;\n 'fx-card': FxComp<FxCardProps>;\n 'fx-breadcrumb': FxComp<FxBreadcrumbProps>;\n 'fx-popover': FxComp<FxPopoverProps>;\n 'fx-stepper': FxComp<FxStepperProps>;\n 'fx-rating': FxComp<FxRatingProps>;\n 'fx-menu': FxComp<FxMenuProps>;\n 'fx-toggle-button-group': FxComp<FxToggleButtonGroupProps>;\n 'fx-empty-state': FxComp<FxEmptyStateProps>;\n 'fx-password-strength': FxComp<FxPasswordStrengthProps>;\n 'fx-timeline': FxComp<FxTimelineProps>;\n 'fx-carousel': FxComp<FxCarouselProps>;\n 'fx-tree': FxComp<FxTreeProps>;\n 'fx-confirmpopup': FxComp<FxConfirmPopupProps>;\n 'fx-knob': FxComp<FxKnobProps>;\n 'fx-accordion': FxComp<FxAccordionProps>;\n 'fx-accordion-panel': FxComp<FxAccordionPanelProps>;\n 'fx-orderlist': FxComp<FxOrderListProps>;\n 'fx-picklist': FxComp<FxPickListProps>;\n }\n}\n\ndeclare module '@vue/runtime-dom' {\n interface IntrinsicElementAttributes {\n 'fx-button': FxButtonProps;\n 'fx-badge': FxBadgeProps;\n 'fx-spinner': FxSpinnerProps;\n 'fx-input': FxInputProps;\n 'fx-select': FxSelectProps;\n 'fx-switch': FxSwitchProps;\n 'fx-checkbox': FxCheckboxProps;\n 'fx-radio': FxRadioProps;\n 'fx-textarea': FxTextareaProps;\n 'fx-multiselect': FxMultiselectProps;\n 'fx-calendar': FxCalendarProps;\n 'fx-datepicker': FxDatepickerProps;\n 'fx-table': FxTableProps;\n 'fx-column': FxColumnProps;\n 'fx-cell': FxCellProps;\n 'fx-toolbar': FxToolbarProps;\n 'fx-floatlabel': FxFloatlabelProps;\n 'fx-dialog': FxDialogProps;\n 'fx-drawer': FxDrawerProps;\n 'fx-toast': FxToastProps;\n 'fx-tooltip': FxTooltipProps;\n 'fx-tabs': FxTabsProps;\n 'fx-tab-panel': FxTabPanelProps;\n 'fx-progress': FxProgressProps;\n 'fx-skeleton': FxSkeletonProps;\n 'fx-alert': FxAlertProps;\n 'fx-dropdown': FxDropdownProps;\n 'fx-dropdown-item': FxDropdownItemProps;\n 'fx-pagination': FxPaginationProps;\n 'fx-autocomplete': FxAutocompleteProps;\n 'fx-fileupload': FxFileUploadProps;\n 'fx-slider': FxSliderProps;\n 'fx-chip': FxChipProps;\n 'fx-avatar': FxAvatarProps;\n 'fx-icon': FxIconProps;\n 'fx-card': FxCardProps;\n 'fx-breadcrumb': FxBreadcrumbProps;\n 'fx-popover': FxPopoverProps;\n 'fx-stepper': FxStepperProps;\n 'fx-rating': FxRatingProps;\n 'fx-menu': FxMenuProps;\n 'fx-toggle-button-group': FxToggleButtonGroupProps;\n 'fx-empty-state': FxEmptyStateProps;\n 'fx-password-strength': FxPasswordStrengthProps;\n 'fx-timeline': FxTimelineProps;\n 'fx-carousel': FxCarouselProps;\n 'fx-tree': FxTreeProps;\n 'fx-confirmpopup': FxConfirmPopupProps;\n 'fx-knob': FxKnobProps;\n 'fx-accordion': FxAccordionProps;\n 'fx-accordion-panel': FxAccordionPanelProps;\n 'fx-orderlist': FxOrderListProps;\n 'fx-picklist': FxPickListProps;\n }\n}\n\n/** Marcador para `import '@wrrdev/fenix-ui/vue'` funcionar como side-effect import. */\nexport const FX_VUE_TYPES = true as const;\n\n/** Reexporta os tipos nomeados de props para consumidores Vue. */\nexport type * from './jsx';\n\n"],"names":[],"mappings":"AA6LO,MAAM,eAAe;"}
@@ -4,8 +4,8 @@ var __typeError = (msg) => {
4
4
  var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5
5
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
6
6
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
7
- var _FxToast_instances, render_fn;
8
- import { a as FENIX_ICON_BASE_CSS, f as fenixIconHtml, e as esc, i as isFenixIconName, l as loadFenixIconsFont } from "./assets/font-CF0TXsAP.js";
7
+ var _FxToast_instances, syncProgress_fn, render_fn;
8
+ import { a as FENIX_ICON_BASE_CSS, f as fenixIconHtml, e as esc, l as loadFenixIconsFont, i as isFenixIconName } from "./assets/font-CF0TXsAP.js";
9
9
  import { s, g } from "./assets/font-CF0TXsAP.js";
10
10
  const lightTokens = {
11
11
  color: {
@@ -3301,12 +3301,16 @@ const _FxTable = class _FxTable extends FxElement {
3301
3301
  "rows",
3302
3302
  "rows-options",
3303
3303
  "striped",
3304
+ "hover",
3305
+ "toolbar",
3304
3306
  "empty-message",
3305
3307
  "pagination-position",
3306
3308
  "lazy",
3307
3309
  "total",
3308
3310
  "loading",
3309
- "loading-message"
3311
+ "loading-message",
3312
+ "sort-field",
3313
+ "sort-order"
3310
3314
  ];
3311
3315
  }
3312
3316
  get data() {
@@ -3335,7 +3339,7 @@ const _FxTable = class _FxTable extends FxElement {
3335
3339
  }
3336
3340
  get columns() {
3337
3341
  return [...this.querySelectorAll("fx-column")].map((c) => {
3338
- const tpl = c.querySelector("template");
3342
+ const tpl = this._resolveCellTemplate(c);
3339
3343
  const direct = tpl ? void 0 : c.innerHTML.trim();
3340
3344
  const align = c.getAttribute("align") ?? "left";
3341
3345
  return {
@@ -3349,13 +3353,71 @@ const _FxTable = class _FxTable extends FxElement {
3349
3353
  };
3350
3354
  });
3351
3355
  }
3356
+ /**
3357
+ * Resolve o template de célula de uma `<fx-column>`, em ordem de prioridade:
3358
+ *
3359
+ * 1. `<fx-cell>` — **recomendado**. Tag própria, sem significado especial
3360
+ * para Vue/React/Angular/Svelte: nenhum framework a intercepta, então o
3361
+ * `innerHTML` sempre chega intacto ao componente. O light DOM do
3362
+ * `<fx-table>` não é exibido (a tabela não usa `<slot>`), então o
3363
+ * conteúdo-fonte nunca aparece na tela.
3364
+ *
3365
+ * ⚠️ O conteúdo é TEXTO CRU para o motor de expressões: o `{{ }}` NÃO é
3366
+ * interpretado pelo framework hospedeiro. Cada um precisa neutralizar a
3367
+ * própria sintaxe antes (ver o cabeçalho do arquivo): `v-pre` no Vue,
3368
+ * `{'{{ }}'}` no JSX, `ngNonBindable` no Angular, string/entidades no
3369
+ * Svelte. Sem isso o template não chega ao `renderCell`.
3370
+ * 2. `template="#id"` (ou `template="id"`) — aponta para um `<template>`
3371
+ * declarado **fora** da tabela, útil em React/Angular, onde é mais
3372
+ * simples manter o markup num único lugar.
3373
+ * 3. `<template>` dentro da coluna — forma **legada**, mantida por
3374
+ * compatibilidade. Em Vue 3 ela vira um bloco do compilador e em React os
3375
+ * filhos são gerenciados pelo framework; nos dois casos o `innerHTML`
3376
+ * chega vazio e a célula não renderiza. Prefira `<fx-cell>`.
3377
+ */
3378
+ _resolveCellTemplate(c) {
3379
+ const cell = c.querySelector(":scope > fx-cell");
3380
+ if (cell) return cell;
3381
+ const ref = c.getAttribute("template");
3382
+ if (ref) {
3383
+ const alvo = this._resolveRef(ref);
3384
+ if (alvo) return alvo;
3385
+ }
3386
+ return c.querySelector("template");
3387
+ }
3352
3388
  get toolbarTemplate() {
3353
- return this.querySelector(
3354
- 'template[slot="toolbar"]'
3355
- );
3389
+ const bar = this.querySelector(":scope > fx-toolbar");
3390
+ if (bar) return bar;
3391
+ const ref = this.getAttr("toolbar");
3392
+ if (ref) {
3393
+ const alvo = this._resolveRef(ref);
3394
+ if (alvo) return alvo;
3395
+ }
3396
+ return this.querySelector('template[slot="toolbar"]');
3397
+ }
3398
+ /**
3399
+ * Resolve `ref` para um elemento: `#id`/`id` ⇒ `getElementById` no
3400
+ * documento; qualquer outro valor é tratado como seletor CSS relativo à
3401
+ * própria tabela. Valores inválidos devolvem `null` (sem exceção).
3402
+ */
3403
+ _resolveRef(ref) {
3404
+ const valor = ref.trim();
3405
+ if (!valor) return null;
3406
+ const doc = this.ownerDocument;
3407
+ if (valor.startsWith("#")) return doc?.getElementById(valor.slice(1)) ?? null;
3408
+ if (/^[.#[>]/.test(valor)) {
3409
+ try {
3410
+ return this.querySelector(valor);
3411
+ } catch {
3412
+ return null;
3413
+ }
3414
+ }
3415
+ return doc?.getElementById(valor) ?? null;
3356
3416
  }
3357
3417
  connectedCallback() {
3358
3418
  this._parseDataAttribute();
3419
+ this._parseSortAttributes();
3420
+ loadFenixIconsFont();
3359
3421
  super.connectedCallback();
3360
3422
  this._columnObserver = new MutationObserver(() => this.render());
3361
3423
  this._columnObserver.observe(this, { childList: true, subtree: true });
@@ -3364,6 +3426,13 @@ const _FxTable = class _FxTable extends FxElement {
3364
3426
  this._columnObserver?.disconnect();
3365
3427
  super.disconnectedCallback();
3366
3428
  }
3429
+ /** Ordenação inicial via `sort-field` / `sort-order` (documentados na API). */
3430
+ _parseSortAttributes() {
3431
+ const field = this.getAttr("sort-field");
3432
+ if (field) this.sortField = field;
3433
+ const order = this.getAttr("sort-order");
3434
+ if (order === "asc" || order === "desc") this.sortDir = order === "asc" ? 1 : -1;
3435
+ }
3367
3436
  _parseDataAttribute() {
3368
3437
  if (!this._data.length) {
3369
3438
  try {
@@ -3447,11 +3516,11 @@ const _FxTable = class _FxTable extends FxElement {
3447
3516
  const pagerHtml = !paginated ? "" : `
3448
3517
  <div class="pager" part="pager">
3449
3518
  <span class="info">Página ${this.page + 1} de ${pages} · ${total} registros</span>
3450
- <button type="button" class="pg-btn" data-pg="first" ${this.page === 0 ? "disabled" : ""}>«</button>
3451
- <button type="button" class="pg-btn" data-pg="prev" ${this.page === 0 ? "disabled" : ""}>‹</button>
3519
+ <button type="button" class="pg-btn" part="first" aria-label="Primeira página" data-pg="first" ${this.page === 0 ? "disabled" : ""}>${fenixIconHtml("first_page")}</button>
3520
+ <button type="button" class="pg-btn" part="prev" aria-label="Página anterior" data-pg="prev" ${this.page === 0 ? "disabled" : ""}>${fenixIconHtml("navigate_before")}</button>
3452
3521
  ${Array.from({ length: pages }, (_, p) => `<button type="button" class="pg-btn" data-pg="${p}" aria-current="${p === this.page}">${p + 1}</button>`).join("")}
3453
- <button type="button" class="pg-btn" data-pg="next" ${this.page >= pages - 1 ? "disabled" : ""}>›</button>
3454
- <button type="button" class="pg-btn" data-pg="last" ${this.page >= pages - 1 ? "disabled" : ""}>»</button>
3522
+ <button type="button" class="pg-btn" part="next" aria-label="Próxima página" data-pg="next" ${this.page >= pages - 1 ? "disabled" : ""}>${fenixIconHtml("navigate_next")}</button>
3523
+ <button type="button" class="pg-btn" part="last" aria-label="Última página" data-pg="last" ${this.page >= pages - 1 ? "disabled" : ""}>${fenixIconHtml("last_page")}</button>
3455
3524
  <label class="info">${esc("Por página:")}
3456
3525
  <fx-select class="rows-sel" size="sm" value="${this.rowsPerPage}" aria-label="Itens por página">${this.getAttr(
3457
3526
  "rows-options",
@@ -3588,6 +3657,7 @@ const _FxTable = class _FxTable extends FxElement {
3588
3657
  }
3589
3658
  };
3590
3659
  _FxTable.styles = css`
3660
+ ${FENIX_ICON_BASE_CSS}
3591
3661
  :host {
3592
3662
  display: block;
3593
3663
  font-family: var(--fx-font-family);
@@ -3664,17 +3734,14 @@ _FxTable.styles = css`
3664
3734
  transition: background-color var(--fx-motion-duration-fast)
3665
3735
  var(--fx-motion-easing);
3666
3736
  }
3667
- tbody tr:hover {
3668
- background: color-mix(
3669
- in srgb,
3670
- var(--fx-color-primary) 8%,
3671
- transparent
3672
- );
3673
- }
3737
+ /* Listrado: alterna a superfície (cinza). Antes usava
3738
+ --fx-surface-background, que é a MESMA cor do fundo do :host e
3739
+ portanto pintava branco sobre branco (listrado invisível). */
3674
3740
  :host([striped]) tbody tr:nth-child(even) {
3675
- background: var(--fx-surface-background);
3741
+ background: var(--fx-surface-surface, #f8fafc);
3676
3742
  }
3677
- :host([striped]) tbody tr:hover {
3743
+ /* O hover é opt-in via atributo (o clique na linha continua sempre ativo). */
3744
+ :host([hover]) tbody tr:hover {
3678
3745
  background: color-mix(
3679
3746
  in srgb,
3680
3747
  var(--fx-color-primary) 8%,
@@ -3704,6 +3771,9 @@ _FxTable.styles = css`
3704
3771
  font-size: calc(var(--fx-font-size) - 2px);
3705
3772
  }
3706
3773
  .pg-btn {
3774
+ display: inline-flex;
3775
+ align-items: center;
3776
+ justify-content: center;
3707
3777
  min-width: var(--fx-size-sm);
3708
3778
  height: var(--fx-size-sm);
3709
3779
  font: inherit;
@@ -3717,6 +3787,12 @@ _FxTable.styles = css`
3717
3787
  transition: border-color var(--fx-motion-duration-fast)
3718
3788
  var(--fx-motion-easing);
3719
3789
  }
3790
+ /* O glifo precisa de 1px a mais que o dígito: a altura de traço do ícone é
3791
+ maior que a do número, então igualar os dois font-size deixa a seta
3792
+ visivelmente maior que o texto. */
3793
+ .pg-btn .fx-icon {
3794
+ font-size: calc(var(--fx-font-size) - 1px);
3795
+ }
3720
3796
  .pg-btn:hover:not(:disabled):not([aria-current="true"]) {
3721
3797
  border-color: var(--fx-color-primary);
3722
3798
  color: var(--fx-color-primary);
@@ -7153,6 +7229,48 @@ const CARD_CSS = `
7153
7229
  color: var(--fx-text-muted, #64748b); font-size: 15px; padding: 2px 4px; border-radius: 4px;
7154
7230
  }
7155
7231
  .close:hover { color: var(--fx-color-danger, #f43f5e); background: var(--fx-surface-surface-hover, rgba(0,0,0,.05)); }
7232
+
7233
+ /* --- Barra de contagem regressiva (atributo progress) ---
7234
+ Fica na base do card e esvazia durante a duração, na cor do kind (--kind) —
7235
+ ou seja, acompanha success/error/warning/info sem configuração extra.
7236
+
7237
+ O lado é configurável pelo atributo progress-origin (padrão: left):
7238
+ left → a barra drena da direita para a esquerda (ancorada à esquerda)
7239
+ right → a barra drena da esquerda para a direita (ancorada à direita)
7240
+ A origem entra como custom property, então os keyframes são compartilhados.
7241
+
7242
+ Usa escalaX em vez de width: a animação escreve só na compositor, sem
7243
+ reflow por frame. */
7244
+ .card { position: relative; overflow: hidden; }
7245
+ .progress {
7246
+ position: absolute;
7247
+ left: 0;
7248
+ bottom: 0;
7249
+ width: 100%;
7250
+ height: 3px;
7251
+ background: var(--kind);
7252
+ transform-origin: var(--toast-progress-origin, left center);
7253
+ transform: scaleX(1);
7254
+ border-radius: 0 0 var(--fx-radius-md, 8px) var(--fx-radius-md, 8px);
7255
+ pointer-events: none;
7256
+ will-change: transform;
7257
+ }
7258
+ .progress.run { animation: fx-toast-drain var(--toast-duration, 4000ms) linear forwards; }
7259
+ /* No modo hover a animação fica parada até o cursor/foco entrar no card. */
7260
+ .card:hover .progress.run,
7261
+ .card:focus-within .progress.run { animation-play-state: running; }
7262
+ @keyframes fx-toast-drain {
7263
+ from { transform: scaleX(1); }
7264
+ to { transform: scaleX(0); }
7265
+ }
7266
+ /* A barra só começa a correr no 2º frame: no 1º ela já apareceria zerada
7267
+ (o elemento acabou de ser inserido e a animação aplica o estado final). */
7268
+ .card.entering .progress { animation: none; }
7269
+ /* Ao dispensar, congela a barra: ela some junto com o card em .2s. */
7270
+ .card.leaving .progress { animation-play-state: paused; }
7271
+ @media (prefers-reduced-motion: reduce) {
7272
+ .progress.run { animation-duration: 0.01ms; }
7273
+ }
7156
7274
  `;
7157
7275
  class FxToast extends HTMLElement {
7158
7276
  constructor() {
@@ -7162,7 +7280,51 @@ class FxToast extends HTMLElement {
7162
7280
  this.attachShadow({ mode: "open" });
7163
7281
  }
7164
7282
  static get observedAttributes() {
7165
- return ["kind", "title", "message", "duration", "icon", "mode"];
7283
+ return ["kind", "title", "message", "duration", "icon", "mode", "progress", "progress-origin"];
7284
+ }
7285
+ /**
7286
+ * Exibe a barra de contagem regressiva na base do card.
7287
+ *
7288
+ * A barra esvazia da esquerda para a direita durante exatamente `duration`
7289
+ * e usa a cor do `kind`. Com `duration="0"` (toast fixo) a barra é
7290
+ * omitida — não há tempo restante a representar.
7291
+ *
7292
+ * - `'always'` (ou atributo vazio): barra sempre correndo.
7293
+ * - `'hover'`: a barra só corre enquanto o cursor estiver sobre o toast;
7294
+ * ao sair, a animação pausa, então dá tempo de ler a mensagem.
7295
+ * - `'paused'`: barra visível, porém parada.
7296
+ */
7297
+ get progress() {
7298
+ if (!this.hasAttribute("progress")) return void 0;
7299
+ const v = this.getAttribute("progress");
7300
+ return v === "hover" || v === "paused" ? v : "always";
7301
+ }
7302
+ set progress(value) {
7303
+ if (value) this.setAttribute("progress", value);
7304
+ else this.removeAttribute("progress");
7305
+ }
7306
+ /**
7307
+ * Lado a partir do qual a barra esvazia.
7308
+ *
7309
+ * - `'left'` (padrão): a barra fica ancorada à esquerda e drena da direita
7310
+ * para a esquerda.
7311
+ * - `'right'`: a barra fica ancorada à direita e drena da esquerda para a
7312
+ * direita (espelhado).
7313
+ *
7314
+ * Só tem efeito junto com `progress`; qualquer valor fora da lista cai em
7315
+ * `'left'`.
7316
+ */
7317
+ get progressOrigin() {
7318
+ return this.getAttribute("progress-origin") === "right" ? "right" : "left";
7319
+ }
7320
+ set progressOrigin(value) {
7321
+ this.setAttribute("progress-origin", value);
7322
+ }
7323
+ /** Duração efetiva em ms (0 = fixo). Mesma regra usada no timer. */
7324
+ get safeDuration() {
7325
+ const dur = Number(this.getAttribute("duration") ?? "4000");
7326
+ if (dur === 0) return 0;
7327
+ return Math.max(Number.isNaN(dur) ? 4e3 : dur, 1e3);
7166
7328
  }
7167
7329
  /** Esquema de cores forçado do card: 'light' | 'dark' | undefined (segue o tema). */
7168
7330
  get mode() {
@@ -7175,16 +7337,21 @@ class FxToast extends HTMLElement {
7175
7337
  }
7176
7338
  connectedCallback() {
7177
7339
  if (!this.shadowRoot.firstChild) __privateMethod(this, _FxToast_instances, render_fn).call(this);
7178
- const dur = Number(this.getAttribute("duration") ?? "4000");
7179
- const safe = dur === 0 ? 0 : Math.max(Number.isNaN(dur) ? 4e3 : dur, 1e3);
7180
- if (!Number.isNaN(safe) && safe > 0 && !this.timer) {
7340
+ const safe = this.safeDuration;
7341
+ if (safe > 0 && !this.timer) {
7181
7342
  this.timer = setTimeout(() => this.dismiss(), safe);
7182
7343
  }
7344
+ __privateMethod(this, _FxToast_instances, syncProgress_fn).call(this);
7183
7345
  }
7184
7346
  disconnectedCallback() {
7185
7347
  if (this.timer) clearTimeout(this.timer);
7186
7348
  this.timer = null;
7187
7349
  }
7350
+ attributeChangedCallback(name) {
7351
+ if (name === "duration" || name === "progress" || name === "progress-origin" || name === "kind") {
7352
+ __privateMethod(this, _FxToast_instances, syncProgress_fn).call(this);
7353
+ }
7354
+ }
7188
7355
  dismiss() {
7189
7356
  if (this.timer) clearTimeout(this.timer);
7190
7357
  this.timer = null;
@@ -7198,6 +7365,36 @@ class FxToast extends HTMLElement {
7198
7365
  }
7199
7366
  }
7200
7367
  _FxToast_instances = new WeakSet();
7368
+ /**
7369
+ * Aplica (ou remove) a barra de contagem regressiva.
7370
+ *
7371
+ * A barra só existe com `progress` e `duration > 0`. O tempo da animação
7372
+ * vem de `--toast-duration`, sempre igual ao do `setTimeout` que fecha o
7373
+ * toast — assim a barra e o desaparecimento nunca desalinham.
7374
+ */
7375
+ syncProgress_fn = function() {
7376
+ const card = this.shadowRoot?.querySelector(".card");
7377
+ if (!card) return;
7378
+ const bar = this.shadowRoot.querySelector(".progress");
7379
+ const mode = this.progress;
7380
+ const dur = this.safeDuration;
7381
+ const shouldShow = !!mode && dur > 0;
7382
+ if (!shouldShow) {
7383
+ bar?.remove();
7384
+ card.classList.remove("entering");
7385
+ return;
7386
+ }
7387
+ if (!bar) {
7388
+ this.shadowRoot.querySelector(".card").insertAdjacentHTML("beforeend", '<span class="progress" part="progress" aria-hidden="true"></span>');
7389
+ }
7390
+ const el = this.shadowRoot.querySelector(".progress");
7391
+ el.style.setProperty("--toast-duration", `${dur}ms`);
7392
+ el.style.setProperty("--toast-progress-origin", `${this.progressOrigin} center`);
7393
+ el.classList.remove("run");
7394
+ if (mode !== "paused") el.classList.add("run");
7395
+ card.classList.add("entering");
7396
+ requestAnimationFrame(() => requestAnimationFrame(() => card.classList.remove("entering")));
7397
+ };
7201
7398
  render_fn = function() {
7202
7399
  const kind = this.getAttribute("kind") || "info";
7203
7400
  const title = this.getAttribute("title") ?? "";
@@ -7267,6 +7464,8 @@ class ToastApi {
7267
7464
  el.setAttribute("position", o.position ?? "top-right");
7268
7465
  el.setAttribute("duration", String(o.duration ?? 4e3));
7269
7466
  if (o.mode) el.setAttribute("mode", o.mode);
7467
+ if (o.progress) el.setAttribute("progress", o.progress);
7468
+ if (o.progressOrigin) el.setAttribute("progress-origin", o.progressOrigin);
7270
7469
  regionFor(o.position ?? "top-right").appendChild(el);
7271
7470
  this.map.set(id, el);
7272
7471
  return id;
@@ -8364,6 +8563,10 @@ _FxDrawer.styles = css`
8364
8563
  position: sticky;
8365
8564
  top: 0;
8366
8565
  background: var(--fx-surface-background);
8566
+ /* O conteúdo do drawer (ex.: abas da customização de tema)
8567
+ rola por trás do header: sem z-index o texto passava POR CIMA
8568
+ e o header parecia transparente. */
8569
+ z-index: 1;
8367
8570
  }
8368
8571
  .title {
8369
8572
  font-weight: 700;
@@ -8428,6 +8631,10 @@ const _FxPagination = class _FxPagination extends FxElement {
8428
8631
  get pages() {
8429
8632
  return Math.max(1, Math.ceil(this.total / this.rows));
8430
8633
  }
8634
+ connectedCallback() {
8635
+ loadFenixIconsFont();
8636
+ super.connectedCallback();
8637
+ }
8431
8638
  render() {
8432
8639
  const pages = this.pages;
8433
8640
  const current = Math.min(Math.max(1, this.page), pages);
@@ -8438,11 +8645,13 @@ const _FxPagination = class _FxPagination extends FxElement {
8438
8645
  const to = Math.min(current * this.rows, this.total);
8439
8646
  this.setTemplate(`
8440
8647
  <span class="info">${this.total ? `${from}-${to} de ${this.total}` : "0 itens"}</span>
8441
- <button type="button" class="nav" part="prev" data-go="${current - 1}" ${current <= 1 ? "disabled" : ""}>‹</button>
8648
+ <button type="button" class="nav" part="first" aria-label="Primeira página" data-go="1" ${current <= 1 ? "disabled" : ""}>${fenixIconHtml("first_page")}</button>
8649
+ <button type="button" class="nav" part="prev" aria-label="Página anterior" data-go="${current - 1}" ${current <= 1 ? "disabled" : ""}>${fenixIconHtml("navigate_before")}</button>
8442
8650
  ${window_[0] !== 1 && pages > 5 ? `<button type="button" class="nav" data-go="1">1</button>` : ""}
8443
8651
  ${window_.map((p) => `<button type="button" class="nav ${p === current ? "active" : ""}" data-go="${p}">${p}</button>`).join("")}
8444
8652
  ${window_[window_.length - 1] !== pages && pages > 5 ? `<button type="button" class="nav" data-go="${pages}">${pages}</button>` : ""}
8445
- <button type="button" class="nav" part="next" data-go="${current + 1}" ${current >= pages ? "disabled" : ""}>›</button>
8653
+ <button type="button" class="nav" part="next" aria-label="Próxima página" data-go="${current + 1}" ${current >= pages ? "disabled" : ""}>${fenixIconHtml("navigate_next")}</button>
8654
+ <button type="button" class="nav" part="last" aria-label="Última página" data-go="${pages}" ${current >= pages ? "disabled" : ""}>${fenixIconHtml("last_page")}</button>
8446
8655
  ${opts.length ? `
8447
8656
  <fx-select class="rows-sel" part="rows" size="sm" value="${this.rows}" aria-label="Itens por página">
8448
8657
  ${opts.map((o) => `<option value="${esc(o)}">${esc(o)}</option>`).join("")}
@@ -8478,6 +8687,7 @@ const _FxPagination = class _FxPagination extends FxElement {
8478
8687
  }
8479
8688
  };
8480
8689
  _FxPagination.styles = css`
8690
+ ${FENIX_ICON_BASE_CSS}
8481
8691
  :host {
8482
8692
  display: flex;
8483
8693
  align-items: center;
@@ -8489,6 +8699,9 @@ _FxPagination.styles = css`
8489
8699
  :host([position='center']) { justify-content: center; }
8490
8700
  :host([position='right']) { justify-content: flex-end; }
8491
8701
  .nav {
8702
+ display: inline-flex;
8703
+ align-items: center;
8704
+ justify-content: center;
8492
8705
  min-width: var(--fx-size-sm);
8493
8706
  height: var(--fx-size-sm);
8494
8707
  border: 1px solid var(--fx-border-default);
@@ -8503,6 +8716,10 @@ _FxPagination.styles = css`
8503
8716
  border-color var(--fx-motion-duration-fast) var(--fx-motion-easing),
8504
8717
  background var(--fx-motion-duration-fast) var(--fx-motion-easing);
8505
8718
  }
8719
+ /* O glifo precisa de 1px a mais que o dígito: a altura de traço do ícone é
8720
+ maior que a do número, então igualar os dois font-size deixa a seta
8721
+ visivelmente maior que o texto. */
8722
+ .nav .fx-icon { font-size: calc(var(--fx-font-size) - 1px); }
8506
8723
  .nav:hover:not([disabled]):not(.active) { border-color: var(--fx-color-primary); color: var(--fx-color-primary); }
8507
8724
  .nav[disabled] { opacity: 0.5; cursor: not-allowed; }
8508
8725
  .nav.active {