@rojaostudio/ds 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +89 -0
- package/brand/rojao-black-on-white.png +0 -0
- package/brand/rojao-black.png +0 -0
- package/brand/rojao-white-on-black.png +0 -0
- package/brand/rojao-white.png +0 -0
- package/dist/chunk-ORMEWXMH.js +37 -0
- package/dist/compat/generate.d.ts +6 -0
- package/dist/compat/generate.js +1 -0
- package/dist/compat/recipes.d.ts +1 -0
- package/dist/compat/recipes.js +1 -0
- package/dist/compat/themes.d.ts +1 -0
- package/dist/compat/themes.js +1 -0
- package/dist/compat/tokens.d.ts +1 -0
- package/dist/compat/tokens.js +1 -0
- package/dist/components/accordion.d.ts +35 -0
- package/dist/components/accordion.js +95 -0
- package/dist/components/alert.d.ts +24 -0
- package/dist/components/alert.js +72 -0
- package/dist/components/avatar.d.ts +45 -0
- package/dist/components/avatar.js +97 -0
- package/dist/components/badge.d.ts +45 -0
- package/dist/components/badge.js +114 -0
- package/dist/components/blocker-card.d.ts +42 -0
- package/dist/components/blocker-card.js +45 -0
- package/dist/components/bottom-sheet.d.ts +31 -0
- package/dist/components/bottom-sheet.js +120 -0
- package/dist/components/breadcrumb.d.ts +28 -0
- package/dist/components/breadcrumb.js +52 -0
- package/dist/components/button.d.ts +27 -0
- package/dist/components/button.js +124 -0
- package/dist/components/card.d.ts +27 -0
- package/dist/components/card.js +52 -0
- package/dist/components/chat-bubble.d.ts +16 -0
- package/dist/components/chat-bubble.js +55 -0
- package/dist/components/checkbox.d.ts +14 -0
- package/dist/components/checkbox.js +78 -0
- package/dist/components/chip-input.d.ts +26 -0
- package/dist/components/chip-input.js +182 -0
- package/dist/components/chips.d.ts +22 -0
- package/dist/components/chips.js +94 -0
- package/dist/components/choice-card.d.ts +16 -0
- package/dist/components/choice-card.js +60 -0
- package/dist/components/choice-carousel.d.ts +16 -0
- package/dist/components/choice-carousel.js +154 -0
- package/dist/components/choice-preview-card.d.ts +37 -0
- package/dist/components/choice-preview-card.js +39 -0
- package/dist/components/color-input.d.ts +20 -0
- package/dist/components/color-input.js +79 -0
- package/dist/components/combobox.d.ts +70 -0
- package/dist/components/combobox.js +213 -0
- package/dist/components/context-menu.d.ts +33 -0
- package/dist/components/context-menu.js +70 -0
- package/dist/components/copilot-hint.d.ts +18 -0
- package/dist/components/copilot-hint.js +63 -0
- package/dist/components/copy-field.d.ts +16 -0
- package/dist/components/copy-field.js +41 -0
- package/dist/components/currency-input.d.ts +32 -0
- package/dist/components/currency-input.js +138 -0
- package/dist/components/danger-zone.d.ts +20 -0
- package/dist/components/danger-zone.js +21 -0
- package/dist/components/data-table-header.d.ts +43 -0
- package/dist/components/data-table-header.js +205 -0
- package/dist/components/date-picker.d.ts +40 -0
- package/dist/components/date-picker.js +252 -0
- package/dist/components/divider.d.ts +20 -0
- package/dist/components/divider.js +47 -0
- package/dist/components/drawer.d.ts +26 -0
- package/dist/components/drawer.js +82 -0
- package/dist/components/dropzone.d.ts +19 -0
- package/dist/components/dropzone.js +65 -0
- package/dist/components/empty-state.d.ts +48 -0
- package/dist/components/empty-state.js +91 -0
- package/dist/components/fab.d.ts +38 -0
- package/dist/components/fab.js +100 -0
- package/dist/components/filter-chip.d.ts +54 -0
- package/dist/components/filter-chip.js +66 -0
- package/dist/components/floating-stepper.d.ts +44 -0
- package/dist/components/floating-stepper.js +53 -0
- package/dist/components/form-card-header.d.ts +13 -0
- package/dist/components/form-card-header.js +8 -0
- package/dist/components/icon-button.d.ts +17 -0
- package/dist/components/icon-button.js +80 -0
- package/dist/components/image-crop-modal.d.ts +59 -0
- package/dist/components/image-crop-modal.js +240 -0
- package/dist/components/image-upload.d.ts +72 -0
- package/dist/components/image-upload.js +271 -0
- package/dist/components/index.d.ts +85 -0
- package/dist/components/index.js +200 -0
- package/dist/components/input.d.ts +25 -0
- package/dist/components/input.js +136 -0
- package/dist/components/insight-card.d.ts +19 -0
- package/dist/components/insight-card.js +27 -0
- package/dist/components/label.d.ts +16 -0
- package/dist/components/label.js +43 -0
- package/dist/components/media-tile.d.ts +24 -0
- package/dist/components/media-tile.js +28 -0
- package/dist/components/menu.d.ts +50 -0
- package/dist/components/menu.js +80 -0
- package/dist/components/modal.d.ts +25 -0
- package/dist/components/modal.js +71 -0
- package/dist/components/notice.d.ts +50 -0
- package/dist/components/notice.js +103 -0
- package/dist/components/option-tile.d.ts +60 -0
- package/dist/components/option-tile.js +144 -0
- package/dist/components/page-shell.d.ts +29 -0
- package/dist/components/page-shell.js +36 -0
- package/dist/components/page-skeleton.d.ts +35 -0
- package/dist/components/page-skeleton.js +12 -0
- package/dist/components/page-tabs.d.ts +35 -0
- package/dist/components/page-tabs.js +55 -0
- package/dist/components/pagination.d.ts +31 -0
- package/dist/components/pagination.js +80 -0
- package/dist/components/paywall-banner.d.ts +37 -0
- package/dist/components/paywall-banner.js +42 -0
- package/dist/components/paywall.d.ts +44 -0
- package/dist/components/paywall.js +55 -0
- package/dist/components/phone-frame.d.ts +9 -0
- package/dist/components/phone-frame.js +18 -0
- package/dist/components/phone-input.d.ts +24 -0
- package/dist/components/phone-input.js +92 -0
- package/dist/components/pix-icon.d.ts +8 -0
- package/dist/components/pix-icon.js +24 -0
- package/dist/components/popover.d.ts +44 -0
- package/dist/components/popover.js +140 -0
- package/dist/components/pricing-card.d.ts +42 -0
- package/dist/components/pricing-card.js +29 -0
- package/dist/components/qr-display.d.ts +19 -0
- package/dist/components/qr-display.js +24 -0
- package/dist/components/radio.d.ts +33 -0
- package/dist/components/radio.js +97 -0
- package/dist/components/row-actions.d.ts +24 -0
- package/dist/components/row-actions.js +76 -0
- package/dist/components/saving-bar-context.d.ts +40 -0
- package/dist/components/saving-bar-context.js +125 -0
- package/dist/components/saving-bar.d.ts +18 -0
- package/dist/components/saving-bar.js +72 -0
- package/dist/components/search.d.ts +30 -0
- package/dist/components/search.js +81 -0
- package/dist/components/section-card.d.ts +14 -0
- package/dist/components/section-card.js +49 -0
- package/dist/components/section-header.d.ts +29 -0
- package/dist/components/section-header.js +7 -0
- package/dist/components/select.d.ts +21 -0
- package/dist/components/select.js +140 -0
- package/dist/components/selectable-card.d.ts +35 -0
- package/dist/components/selectable-card.js +27 -0
- package/dist/components/setting-row.d.ts +33 -0
- package/dist/components/setting-row.js +19 -0
- package/dist/components/settings-list.d.ts +25 -0
- package/dist/components/settings-list.js +22 -0
- package/dist/components/skeleton.d.ts +24 -0
- package/dist/components/skeleton.js +49 -0
- package/dist/components/slider.d.ts +32 -0
- package/dist/components/slider.js +79 -0
- package/dist/components/spinner.d.ts +14 -0
- package/dist/components/spinner.js +36 -0
- package/dist/components/step-progress.d.ts +12 -0
- package/dist/components/step-progress.js +24 -0
- package/dist/components/summary-bar.d.ts +31 -0
- package/dist/components/summary-bar.js +54 -0
- package/dist/components/table.d.ts +23 -0
- package/dist/components/table.js +80 -0
- package/dist/components/textarea.d.ts +21 -0
- package/dist/components/textarea.js +95 -0
- package/dist/components/themed.d.ts +36 -0
- package/dist/components/themed.js +22 -0
- package/dist/components/time-picker.d.ts +34 -0
- package/dist/components/time-picker.js +213 -0
- package/dist/components/toaster.d.ts +84 -0
- package/dist/components/toaster.js +284 -0
- package/dist/components/toggle-card-compact.d.ts +21 -0
- package/dist/components/toggle-card-compact.js +99 -0
- package/dist/components/toggle-card.d.ts +15 -0
- package/dist/components/toggle-card.js +76 -0
- package/dist/components/toggle-group.d.ts +67 -0
- package/dist/components/toggle-group.js +80 -0
- package/dist/components/toggle.d.ts +13 -0
- package/dist/components/toggle.js +64 -0
- package/dist/components/tooltip.d.ts +17 -0
- package/dist/components/tooltip.js +89 -0
- package/dist/components/typing-indicator.d.ts +8 -0
- package/dist/components/typing-indicator.js +27 -0
- package/dist/components/use-dismiss.d.ts +9 -0
- package/dist/components/use-dismiss.js +28 -0
- package/dist/components/use-focus-trap.d.ts +5 -0
- package/dist/components/use-focus-trap.js +54 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +89 -0
- package/dist/targets/native/components/accordion.d.ts +18 -0
- package/dist/targets/native/components/accordion.js +122 -0
- package/dist/targets/native/components/alert.d.ts +16 -0
- package/dist/targets/native/components/alert.js +58 -0
- package/dist/targets/native/components/avatar.d.ts +25 -0
- package/dist/targets/native/components/avatar.js +88 -0
- package/dist/targets/native/components/badge.d.ts +27 -0
- package/dist/targets/native/components/badge.js +59 -0
- package/dist/targets/native/components/button.d.ts +18 -0
- package/dist/targets/native/components/button.js +84 -0
- package/dist/targets/native/components/card.d.ts +6 -0
- package/dist/targets/native/components/card.js +36 -0
- package/dist/targets/native/components/checkbox.d.ts +12 -0
- package/dist/targets/native/components/checkbox.js +59 -0
- package/dist/targets/native/components/chips.d.ts +17 -0
- package/dist/targets/native/components/chips.js +77 -0
- package/dist/targets/native/components/choice-card.d.ts +11 -0
- package/dist/targets/native/components/choice-card.js +52 -0
- package/dist/targets/native/components/context-menu.d.ts +11 -0
- package/dist/targets/native/components/context-menu.js +19 -0
- package/dist/targets/native/components/currency-input.d.ts +22 -0
- package/dist/targets/native/components/currency-input.js +105 -0
- package/dist/targets/native/components/danger-zone.d.ts +13 -0
- package/dist/targets/native/components/danger-zone.js +27 -0
- package/dist/targets/native/components/date-picker.d.ts +13 -0
- package/dist/targets/native/components/date-picker.js +185 -0
- package/dist/targets/native/components/divider.d.ts +9 -0
- package/dist/targets/native/components/divider.js +36 -0
- package/dist/targets/native/components/empty-state.d.ts +13 -0
- package/dist/targets/native/components/empty-state.js +10 -0
- package/dist/targets/native/components/fab.d.ts +25 -0
- package/dist/targets/native/components/fab.js +112 -0
- package/dist/targets/native/components/filter-chip.d.ts +22 -0
- package/dist/targets/native/components/filter-chip.js +70 -0
- package/dist/targets/native/components/form-field.d.ts +13 -0
- package/dist/targets/native/components/form-field.js +29 -0
- package/dist/targets/native/components/form-screen.d.ts +19 -0
- package/dist/targets/native/components/form-screen.js +88 -0
- package/dist/targets/native/components/google-icon.d.ts +8 -0
- package/dist/targets/native/components/google-icon.js +32 -0
- package/dist/targets/native/components/icon-button.d.ts +18 -0
- package/dist/targets/native/components/icon-button.js +80 -0
- package/dist/targets/native/components/icon.d.ts +11 -0
- package/dist/targets/native/components/icon.js +9 -0
- package/dist/targets/native/components/image-upload.d.ts +12 -0
- package/dist/targets/native/components/image-upload.js +95 -0
- package/dist/targets/native/components/index.d.ts +45 -0
- package/dist/targets/native/components/index.js +100 -0
- package/dist/targets/native/components/input.d.ts +17 -0
- package/dist/targets/native/components/input.js +103 -0
- package/dist/targets/native/components/list-item.d.ts +20 -0
- package/dist/targets/native/components/list-item.js +71 -0
- package/dist/targets/native/components/menu.d.ts +24 -0
- package/dist/targets/native/components/menu.js +71 -0
- package/dist/targets/native/components/modal.d.ts +15 -0
- package/dist/targets/native/components/modal.js +110 -0
- package/dist/targets/native/components/paywall-banner.d.ts +11 -0
- package/dist/targets/native/components/paywall-banner.js +46 -0
- package/dist/targets/native/components/paywall.d.ts +18 -0
- package/dist/targets/native/components/paywall.js +61 -0
- package/dist/targets/native/components/radio.d.ts +20 -0
- package/dist/targets/native/components/radio.js +71 -0
- package/dist/targets/native/components/search.d.ts +22 -0
- package/dist/targets/native/components/search.js +92 -0
- package/dist/targets/native/components/select.d.ts +17 -0
- package/dist/targets/native/components/select.js +86 -0
- package/dist/targets/native/components/sheet.d.ts +11 -0
- package/dist/targets/native/components/sheet.js +51 -0
- package/dist/targets/native/components/skeleton.d.ts +18 -0
- package/dist/targets/native/components/skeleton.js +52 -0
- package/dist/targets/native/components/slider.d.ts +18 -0
- package/dist/targets/native/components/slider.js +153 -0
- package/dist/targets/native/components/spinner.d.ts +7 -0
- package/dist/targets/native/components/spinner.js +10 -0
- package/dist/targets/native/components/stepper.d.ts +10 -0
- package/dist/targets/native/components/stepper.js +33 -0
- package/dist/targets/native/components/switch.d.ts +20 -0
- package/dist/targets/native/components/switch.js +68 -0
- package/dist/targets/native/components/text.d.ts +12 -0
- package/dist/targets/native/components/text.js +31 -0
- package/dist/targets/native/components/textarea.d.ts +13 -0
- package/dist/targets/native/components/textarea.js +92 -0
- package/dist/targets/native/components/theme.d.ts +18 -0
- package/dist/targets/native/components/theme.js +20 -0
- package/dist/targets/native/components/toaster.d.ts +35 -0
- package/dist/targets/native/components/toaster.js +159 -0
- package/dist/targets/native/fonts.d.ts +9 -0
- package/dist/targets/native/fonts.js +10 -0
- package/dist/targets/native/icons.d.ts +1 -0
- package/dist/targets/native/icons.js +1 -0
- package/dist/targets/native/index.d.ts +3 -0
- package/dist/targets/native/index.js +11 -0
- package/dist/targets/native/preset.cjs +69 -0
- package/dist/targets/native/resolve.d.ts +22 -0
- package/dist/targets/native/resolve.js +85 -0
- package/dist/targets/native/theme.css +118 -0
- package/dist/targets/native/theme.d.ts +117 -0
- package/dist/targets/native/theme.js +118 -0
- package/package.json +194 -0
- package/styles/_primitives.generated.css +284 -0
- package/styles/base.css +950 -0
- package/styles/themes/rojao.css +107 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type SummaryBarTone = 'default' | 'positive' | 'negative' | 'warning' | 'muted';
|
|
5
|
+
interface SummaryBarItem {
|
|
6
|
+
/** Short label, e.g. "Valor em estoque" */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Pre-formatted value (currency, count, etc.) — formatting is the consumer's job */
|
|
9
|
+
value: string;
|
|
10
|
+
/** Tints the value. Counters use warning/negative; money uses default/positive. */
|
|
11
|
+
tone?: SummaryBarTone;
|
|
12
|
+
/** Optional leading icon shown before the value */
|
|
13
|
+
icon?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
interface SummaryBarProps {
|
|
16
|
+
items: SummaryBarItem[];
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Strip of aggregated metrics shown above a list (stock summary, finance totals,
|
|
21
|
+
* report KPIs). Mobile: grid 2-colunas (não estoura nem esconde scroll). sm+: linha
|
|
22
|
+
* flex com scroll horizontal se precisar. Contagem ímpar → último item ocupa a linha
|
|
23
|
+
* inteira no mobile (sem célula vazia). Valores são pré-formatados pelo consumidor.
|
|
24
|
+
*
|
|
25
|
+
* Truque do divisor: no mobile, o fundo do CONTAINER é a cor do divisor e o gap-px
|
|
26
|
+
* revela essa cor entre as células (cada célula tem o fundo normal) → linhas de grade
|
|
27
|
+
* limpas. No sm+, o fundo volta ao normal e os divisores são border-left por item.
|
|
28
|
+
*/
|
|
29
|
+
declare function SummaryBar({ items, className }: SummaryBarProps): react.JSX.Element;
|
|
30
|
+
|
|
31
|
+
export { SummaryBar, type SummaryBarItem, type SummaryBarProps, type SummaryBarTone };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import "../chunk-ORMEWXMH.js";
|
|
2
|
+
const TONE_CLASS = {
|
|
3
|
+
default: "[color:var(--summary-bar-value)]",
|
|
4
|
+
positive: "[color:var(--summary-bar-value-positive)]",
|
|
5
|
+
negative: "[color:var(--summary-bar-value-negative)]",
|
|
6
|
+
warning: "[color:var(--summary-bar-value-warning)]",
|
|
7
|
+
muted: "[color:var(--summary-bar-value-muted)]"
|
|
8
|
+
};
|
|
9
|
+
function SummaryBar({ items, className }) {
|
|
10
|
+
const odd = items.length % 2 === 1;
|
|
11
|
+
return /* @__PURE__ */ React.createElement(
|
|
12
|
+
"div",
|
|
13
|
+
{
|
|
14
|
+
className: [
|
|
15
|
+
"grid grid-cols-2 gap-px overflow-hidden rounded-(--radius-card) border",
|
|
16
|
+
"sm:flex sm:gap-0 sm:overflow-x-auto sm:[scrollbar-width:none]",
|
|
17
|
+
"[background:var(--summary-bar-divider)] sm:[background:var(--summary-bar-bg)]",
|
|
18
|
+
"[border-color:var(--summary-bar-border)]",
|
|
19
|
+
className != null ? className : ""
|
|
20
|
+
].join(" ")
|
|
21
|
+
},
|
|
22
|
+
items.map((item, i) => {
|
|
23
|
+
var _a;
|
|
24
|
+
const spanFull = odd && i === items.length - 1;
|
|
25
|
+
return /* @__PURE__ */ React.createElement(
|
|
26
|
+
"div",
|
|
27
|
+
{
|
|
28
|
+
key: i,
|
|
29
|
+
className: [
|
|
30
|
+
"flex flex-1 flex-col gap-1.5 px-4 py-3 [background:var(--summary-bar-bg)]",
|
|
31
|
+
"min-w-0 sm:min-w-[7.5rem] sm:whitespace-nowrap",
|
|
32
|
+
spanFull ? "col-span-2 sm:col-span-1" : "",
|
|
33
|
+
i > 0 ? "sm:[border-left:1px_solid_var(--summary-bar-divider)]" : ""
|
|
34
|
+
].join(" ")
|
|
35
|
+
},
|
|
36
|
+
/* @__PURE__ */ React.createElement("span", { className: "text-[11px] font-medium uppercase tracking-wide [color:var(--summary-bar-label)]" }, item.label),
|
|
37
|
+
/* @__PURE__ */ React.createElement(
|
|
38
|
+
"span",
|
|
39
|
+
{
|
|
40
|
+
className: [
|
|
41
|
+
"flex items-center gap-1.5 text-heading-sm font-semibold leading-none tabular-nums",
|
|
42
|
+
TONE_CLASS[(_a = item.tone) != null ? _a : "default"]
|
|
43
|
+
].join(" ")
|
|
44
|
+
},
|
|
45
|
+
item.icon,
|
|
46
|
+
item.value
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
SummaryBar
|
|
54
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
type Align = 'left' | 'right' | 'center';
|
|
4
|
+
declare function Table({ className, children, ...props }: React.HTMLAttributes<HTMLTableElement>): react.JSX.Element;
|
|
5
|
+
declare function TableHead({ className, children, ...props }: React.HTMLAttributes<HTMLTableSectionElement>): react.JSX.Element;
|
|
6
|
+
declare function TableBody({ className, children, ...props }: React.HTMLAttributes<HTMLTableSectionElement>): react.JSX.Element;
|
|
7
|
+
interface TableRowProps extends React.HTMLAttributes<HTMLTableRowElement> {
|
|
8
|
+
header?: boolean;
|
|
9
|
+
noHover?: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare function TableRow({ header, noHover, className, children, onClick, ...props }: TableRowProps): react.JSX.Element;
|
|
12
|
+
interface ThProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
|
|
13
|
+
align?: Align;
|
|
14
|
+
}
|
|
15
|
+
declare function Th({ align, className, children, ...props }: ThProps): react.JSX.Element;
|
|
16
|
+
interface TdProps extends React.TdHTMLAttributes<HTMLTableCellElement> {
|
|
17
|
+
align?: Align;
|
|
18
|
+
muted?: boolean;
|
|
19
|
+
bold?: boolean;
|
|
20
|
+
}
|
|
21
|
+
declare function Td({ align, muted, bold, className, children, ...props }: TdProps): react.JSX.Element;
|
|
22
|
+
|
|
23
|
+
export { Table, TableBody, TableHead, TableRow, type TableRowProps, Td, type TdProps, Th, type ThProps };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__objRest,
|
|
3
|
+
__spreadValues
|
|
4
|
+
} from "../chunk-ORMEWXMH.js";
|
|
5
|
+
const ALIGN = { left: "text-left", right: "text-right", center: "text-center" };
|
|
6
|
+
function Table(_a) {
|
|
7
|
+
var _b = _a, { className = "", children } = _b, props = __objRest(_b, ["className", "children"]);
|
|
8
|
+
return /* @__PURE__ */ React.createElement("table", __spreadValues({ className: ["w-full text-label", className].join(" ") }, props), children);
|
|
9
|
+
}
|
|
10
|
+
function TableHead(_c) {
|
|
11
|
+
var _d = _c, { className = "", children } = _d, props = __objRest(_d, ["className", "children"]);
|
|
12
|
+
return /* @__PURE__ */ React.createElement("thead", __spreadValues({ className: className || void 0 }, props), children);
|
|
13
|
+
}
|
|
14
|
+
function TableBody(_e) {
|
|
15
|
+
var _f = _e, { className = "", children } = _f, props = __objRest(_f, ["className", "children"]);
|
|
16
|
+
return /* @__PURE__ */ React.createElement("tbody", __spreadValues({ className: ["divide-y divide-stroke-default", className].join(" ") }, props), children);
|
|
17
|
+
}
|
|
18
|
+
function TableRow(_g) {
|
|
19
|
+
var _h = _g, { header, noHover, className = "", children, onClick } = _h, props = __objRest(_h, ["header", "noHover", "className", "children", "onClick"]);
|
|
20
|
+
const base = header ? "border-b border-stroke-default" : [
|
|
21
|
+
!noHover && "hover:bg-surface-raised transition-colors",
|
|
22
|
+
onClick && "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-stroke-focus"
|
|
23
|
+
].filter(Boolean).join(" ");
|
|
24
|
+
const interactiveProps = !header && onClick ? {
|
|
25
|
+
role: "button",
|
|
26
|
+
tabIndex: 0,
|
|
27
|
+
onKeyDown: (e) => {
|
|
28
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
onClick(e);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
} : {};
|
|
34
|
+
return /* @__PURE__ */ React.createElement(
|
|
35
|
+
"tr",
|
|
36
|
+
__spreadValues(__spreadValues({
|
|
37
|
+
className: [base, className].filter(Boolean).join(" "),
|
|
38
|
+
onClick
|
|
39
|
+
}, interactiveProps), props),
|
|
40
|
+
children
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
function Th(_i) {
|
|
44
|
+
var _j = _i, { align = "left", className = "", children } = _j, props = __objRest(_j, ["align", "className", "children"]);
|
|
45
|
+
return /* @__PURE__ */ React.createElement(
|
|
46
|
+
"th",
|
|
47
|
+
__spreadValues({
|
|
48
|
+
className: [
|
|
49
|
+
"px-5 py-3 text-caption font-semibold text-fg-muted uppercase tracking-wide whitespace-nowrap",
|
|
50
|
+
ALIGN[align],
|
|
51
|
+
className
|
|
52
|
+
].filter(Boolean).join(" ")
|
|
53
|
+
}, props),
|
|
54
|
+
children
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
function Td(_k) {
|
|
58
|
+
var _l = _k, { align = "left", muted, bold, className = "", children } = _l, props = __objRest(_l, ["align", "muted", "bold", "className", "children"]);
|
|
59
|
+
return /* @__PURE__ */ React.createElement(
|
|
60
|
+
"td",
|
|
61
|
+
__spreadValues({
|
|
62
|
+
className: [
|
|
63
|
+
"px-5 py-3",
|
|
64
|
+
ALIGN[align],
|
|
65
|
+
muted ? "text-fg-muted" : "text-fg-primary",
|
|
66
|
+
bold ? "font-medium" : "",
|
|
67
|
+
className
|
|
68
|
+
].filter(Boolean).join(" ")
|
|
69
|
+
}, props),
|
|
70
|
+
children
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
Table,
|
|
75
|
+
TableBody,
|
|
76
|
+
TableHead,
|
|
77
|
+
TableRow,
|
|
78
|
+
Td,
|
|
79
|
+
Th
|
|
80
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { TextareaHTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
5
|
+
label?: string;
|
|
6
|
+
helper?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
optional?: boolean;
|
|
10
|
+
/** Auto-cresce conforme conteúdo (sem scroll bar interna). default = false. */
|
|
11
|
+
autoResize?: boolean;
|
|
12
|
+
/** Conta caracteres (mostra "X/Y" se maxLength definido). */
|
|
13
|
+
showCount?: boolean;
|
|
14
|
+
/** Min rows quando autoResize. default = 3. */
|
|
15
|
+
minRows?: number;
|
|
16
|
+
/** Max rows quando autoResize (cap pra evitar crescer infinito). default = 10. */
|
|
17
|
+
maxRows?: number;
|
|
18
|
+
}
|
|
19
|
+
declare const Textarea: react.ForwardRefExoticComponent<TextareaProps & react.RefAttributes<HTMLTextAreaElement>>;
|
|
20
|
+
|
|
21
|
+
export { Textarea, type TextareaProps };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
__objRest,
|
|
4
|
+
__spreadValues
|
|
5
|
+
} from "../chunk-ORMEWXMH.js";
|
|
6
|
+
import { forwardRef, useId, useEffect, useRef } from "react";
|
|
7
|
+
const Textarea = forwardRef(function Textarea2(_a, ref) {
|
|
8
|
+
var _b = _a, {
|
|
9
|
+
label,
|
|
10
|
+
helper,
|
|
11
|
+
error,
|
|
12
|
+
required,
|
|
13
|
+
optional,
|
|
14
|
+
autoResize = false,
|
|
15
|
+
showCount,
|
|
16
|
+
minRows = 3,
|
|
17
|
+
maxRows = 10,
|
|
18
|
+
className = "",
|
|
19
|
+
id,
|
|
20
|
+
rows,
|
|
21
|
+
value,
|
|
22
|
+
defaultValue,
|
|
23
|
+
maxLength,
|
|
24
|
+
onChange
|
|
25
|
+
} = _b, props = __objRest(_b, [
|
|
26
|
+
"label",
|
|
27
|
+
"helper",
|
|
28
|
+
"error",
|
|
29
|
+
"required",
|
|
30
|
+
"optional",
|
|
31
|
+
"autoResize",
|
|
32
|
+
"showCount",
|
|
33
|
+
"minRows",
|
|
34
|
+
"maxRows",
|
|
35
|
+
"className",
|
|
36
|
+
"id",
|
|
37
|
+
"rows",
|
|
38
|
+
"value",
|
|
39
|
+
"defaultValue",
|
|
40
|
+
"maxLength",
|
|
41
|
+
"onChange"
|
|
42
|
+
]);
|
|
43
|
+
const generatedId = useId();
|
|
44
|
+
const textareaId = id != null ? id : generatedId;
|
|
45
|
+
const internalRef = useRef(null);
|
|
46
|
+
function setRef(el) {
|
|
47
|
+
internalRef.current = el;
|
|
48
|
+
if (typeof ref === "function") ref(el);
|
|
49
|
+
else if (ref) ref.current = el;
|
|
50
|
+
}
|
|
51
|
+
function adjust() {
|
|
52
|
+
const el = internalRef.current;
|
|
53
|
+
if (!el || !autoResize) return;
|
|
54
|
+
el.style.height = "auto";
|
|
55
|
+
const lineHeight = parseFloat(getComputedStyle(el).lineHeight || "20");
|
|
56
|
+
const maxH = lineHeight * maxRows + 24;
|
|
57
|
+
el.style.height = `${Math.min(el.scrollHeight, maxH)}px`;
|
|
58
|
+
el.style.overflowY = el.scrollHeight > maxH ? "auto" : "hidden";
|
|
59
|
+
}
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
adjust();
|
|
62
|
+
}, [value, autoResize]);
|
|
63
|
+
function handleChange(e) {
|
|
64
|
+
onChange == null ? void 0 : onChange(e);
|
|
65
|
+
if (autoResize) adjust();
|
|
66
|
+
}
|
|
67
|
+
const currentLength = typeof value === "string" ? value.length : typeof defaultValue === "string" ? defaultValue.length : 0;
|
|
68
|
+
return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1.5 w-full" }, label && /* @__PURE__ */ React.createElement("label", { htmlFor: textareaId, className: "inline-flex items-center gap-1 text-label font-medium text-fg-primary" }, /* @__PURE__ */ React.createElement("span", null, label), required && /* @__PURE__ */ React.createElement("span", { className: "text-danger", "aria-label": "obrigat\xF3rio" }, "*"), optional && !required && /* @__PURE__ */ React.createElement("span", { className: "text-fg-muted font-normal" }, "(opcional)")), /* @__PURE__ */ React.createElement(
|
|
69
|
+
"textarea",
|
|
70
|
+
__spreadValues({
|
|
71
|
+
ref: setRef,
|
|
72
|
+
id: textareaId,
|
|
73
|
+
rows: rows != null ? rows : minRows,
|
|
74
|
+
value,
|
|
75
|
+
defaultValue,
|
|
76
|
+
maxLength,
|
|
77
|
+
required,
|
|
78
|
+
onChange: handleChange,
|
|
79
|
+
className: [
|
|
80
|
+
"w-full px-3 py-2 rounded-(--radius-control) text-label",
|
|
81
|
+
"bg-surface-default text-fg-primary placeholder:text-fg-placeholder",
|
|
82
|
+
"border transition-colors outline-none",
|
|
83
|
+
autoResize ? "resize-none overflow-hidden" : "resize-y",
|
|
84
|
+
error ? "border-danger focus:border-danger focus:ring-2 focus:ring-danger/20" : "border-stroke-control focus:border-stroke-focus focus:ring-2 focus:ring-stroke-focus/20",
|
|
85
|
+
"disabled:opacity-50 disabled:cursor-not-allowed disabled:resize-none",
|
|
86
|
+
className
|
|
87
|
+
].filter(Boolean).join(" "),
|
|
88
|
+
"aria-invalid": error ? true : void 0,
|
|
89
|
+
"aria-describedby": error ? `${textareaId}-error` : helper ? `${textareaId}-helper` : void 0
|
|
90
|
+
}, props)
|
|
91
|
+
), (error || helper || showCount && maxLength) && /* @__PURE__ */ React.createElement("div", { className: "flex items-start justify-between gap-3" }, error ? /* @__PURE__ */ React.createElement("p", { id: `${textareaId}-error`, className: "text-caption text-danger-text flex-1" }, error) : helper ? /* @__PURE__ */ React.createElement("p", { id: `${textareaId}-helper`, className: "text-caption text-fg-muted flex-1" }, helper) : /* @__PURE__ */ React.createElement("span", { className: "flex-1" }), showCount && maxLength && /* @__PURE__ */ React.createElement("span", { className: "text-caption text-fg-muted tabular-nums shrink-0" }, currentLength, "/", maxLength)));
|
|
92
|
+
});
|
|
93
|
+
export {
|
|
94
|
+
Textarea
|
|
95
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* className for a brand theme: `theme-<name>` (+ ` dark`). The DS theme CSS is
|
|
6
|
+
* class-scoped, so apply this wherever you want the theme to take effect — on
|
|
7
|
+
* `<html>`/`<body>` for the whole app, or via <Themed> for a subtree.
|
|
8
|
+
*
|
|
9
|
+
* <html className={themeClass('padaria', isDark)}>
|
|
10
|
+
*/
|
|
11
|
+
declare const themeClass: (theme: string, dark?: boolean) => string;
|
|
12
|
+
interface ThemedProps extends HTMLAttributes<HTMLDivElement> {
|
|
13
|
+
/** Brand theme name → `.theme-<name>` (the served sheet's selector). */
|
|
14
|
+
theme: string;
|
|
15
|
+
/** Apply dark mode (`.dark`). */
|
|
16
|
+
dark?: boolean;
|
|
17
|
+
/** Merge the theme class onto the single child element instead of wrapping a
|
|
18
|
+
* `<div>` (no extra DOM node — apply the theme to a `<main>`, `<section>`…). */
|
|
19
|
+
asChild?: boolean;
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Scopes a brand theme to its subtree via the `.theme-<name>` class. Because the
|
|
24
|
+
* theme CSS is class-scoped (not :root), this can NEST — different subtrees can
|
|
25
|
+
* render different themes on the same page. For the whole app, prefer putting
|
|
26
|
+
* `themeClass()` on `<html>` instead of wrapping everything in a div.
|
|
27
|
+
*
|
|
28
|
+
* <Themed theme="padaria">…</Themed>
|
|
29
|
+
* <Themed theme="pet" dark>…</Themed>
|
|
30
|
+
* <Themed theme="cafe" asChild><main>…</main></Themed>
|
|
31
|
+
*
|
|
32
|
+
* Pair with the brand sheet (ds.rojao.ai/themes/<slug>.css) + base.css.
|
|
33
|
+
*/
|
|
34
|
+
declare function Themed({ theme, dark, asChild, className, children, ...rest }: ThemedProps): react.JSX.Element;
|
|
35
|
+
|
|
36
|
+
export { Themed, type ThemedProps, themeClass };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__objRest,
|
|
3
|
+
__spreadProps,
|
|
4
|
+
__spreadValues
|
|
5
|
+
} from "../chunk-ORMEWXMH.js";
|
|
6
|
+
import { cloneElement, isValidElement } from "react";
|
|
7
|
+
const themeClass = (theme, dark = false) => `theme-${theme}${dark ? " dark" : ""}`;
|
|
8
|
+
function Themed(_a) {
|
|
9
|
+
var _b = _a, { theme, dark = false, asChild = false, className, children } = _b, rest = __objRest(_b, ["theme", "dark", "asChild", "className", "children"]);
|
|
10
|
+
const cls = themeClass(theme, dark);
|
|
11
|
+
if (asChild && isValidElement(children)) {
|
|
12
|
+
const child = children;
|
|
13
|
+
return cloneElement(child, __spreadProps(__spreadValues({}, rest), {
|
|
14
|
+
className: [cls, child.props.className, className].filter(Boolean).join(" ")
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
return /* @__PURE__ */ React.createElement("div", __spreadValues({ className: [cls, className].filter(Boolean).join(" ") }, rest), children);
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
Themed,
|
|
21
|
+
themeClass
|
|
22
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TimePicker — input de hora (HH:mm) com popover de seletor.
|
|
5
|
+
*
|
|
6
|
+
* Uso:
|
|
7
|
+
* <TimePicker value="09:30" onChange={setTime} />
|
|
8
|
+
* <TimePicker value={null} onChange={setTime} step={15} /> // múltiplos de 15min
|
|
9
|
+
* <TimePicker value="14:00" onChange={setTime} format="12h" />
|
|
10
|
+
*
|
|
11
|
+
* Valor é string "HH:mm" (24h) ou null. Lib calling code converte se precisar Date.
|
|
12
|
+
* Confirma via botão "OK". ESC e clique fora descartam o rascunho.
|
|
13
|
+
*/
|
|
14
|
+
interface TimePickerProps {
|
|
15
|
+
value: string | null;
|
|
16
|
+
onChange: (time: string | null) => void;
|
|
17
|
+
/** Step de minutos. default = 1. Use 5/15/30 pra agendamentos. */
|
|
18
|
+
step?: number;
|
|
19
|
+
/** Formato exibido. default = '24h'. */
|
|
20
|
+
format?: '24h' | '12h';
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
size?: 'sm' | 'md';
|
|
23
|
+
width?: 'full' | 'hug';
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
/** Hora mínima permitida ("HH:mm"). */
|
|
26
|
+
min?: string;
|
|
27
|
+
/** Hora máxima permitida ("HH:mm"). */
|
|
28
|
+
max?: string;
|
|
29
|
+
className?: string;
|
|
30
|
+
'aria-label'?: string;
|
|
31
|
+
}
|
|
32
|
+
declare const TimePicker: react.ForwardRefExoticComponent<TimePickerProps & react.RefAttributes<HTMLButtonElement>>;
|
|
33
|
+
|
|
34
|
+
export { TimePicker, type TimePickerProps };
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
__spreadProps,
|
|
4
|
+
__spreadValues
|
|
5
|
+
} from "../chunk-ORMEWXMH.js";
|
|
6
|
+
import { forwardRef, useState, useRef, useEffect, useImperativeHandle } from "react";
|
|
7
|
+
import { Clock, ChevronUp, ChevronDown, X } from "lucide-react";
|
|
8
|
+
import { Popover } from "./popover.js";
|
|
9
|
+
const SIZE_CLASS = {
|
|
10
|
+
sm: "h-8 text-caption px-2.5",
|
|
11
|
+
md: "h-10 text-label px-3"
|
|
12
|
+
};
|
|
13
|
+
function parseTime(t) {
|
|
14
|
+
if (!t) return null;
|
|
15
|
+
const match = t.match(/^(\d{1,2}):(\d{2})$/);
|
|
16
|
+
if (!match) return null;
|
|
17
|
+
const h = parseInt(match[1], 10);
|
|
18
|
+
const m = parseInt(match[2], 10);
|
|
19
|
+
if (h < 0 || h > 23 || m < 0 || m > 59) return null;
|
|
20
|
+
return { h, m };
|
|
21
|
+
}
|
|
22
|
+
function formatTime(h, m, format) {
|
|
23
|
+
const mm = String(m).padStart(2, "0");
|
|
24
|
+
if (format === "24h") return `${String(h).padStart(2, "0")}:${mm}`;
|
|
25
|
+
const period = h >= 12 ? "PM" : "AM";
|
|
26
|
+
const h12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
27
|
+
return `${String(h12).padStart(2, "0")}:${mm} ${period}`;
|
|
28
|
+
}
|
|
29
|
+
function clampMinute(m, step) {
|
|
30
|
+
return Math.round(m / step) * step % 60;
|
|
31
|
+
}
|
|
32
|
+
function compareTime(a, b) {
|
|
33
|
+
const pa = parseTime(a);
|
|
34
|
+
const pb = parseTime(b);
|
|
35
|
+
return pa.h * 60 + pa.m - (pb.h * 60 + pb.m);
|
|
36
|
+
}
|
|
37
|
+
const TimePicker = forwardRef(function TimePicker2({
|
|
38
|
+
value,
|
|
39
|
+
onChange,
|
|
40
|
+
step = 1,
|
|
41
|
+
format = "24h",
|
|
42
|
+
placeholder = "HH:mm",
|
|
43
|
+
size = "md",
|
|
44
|
+
width = "full",
|
|
45
|
+
disabled = false,
|
|
46
|
+
min,
|
|
47
|
+
max,
|
|
48
|
+
className = "",
|
|
49
|
+
"aria-label": ariaLabel
|
|
50
|
+
}, ref) {
|
|
51
|
+
const [open, setOpen] = useState(false);
|
|
52
|
+
const [draft, setDraft] = useState(() => {
|
|
53
|
+
const p = parseTime(value);
|
|
54
|
+
return p != null ? p : { h: 9, m: 0 };
|
|
55
|
+
});
|
|
56
|
+
const triggerRef = useRef(null);
|
|
57
|
+
const draftRef = useRef(draft);
|
|
58
|
+
draftRef.current = draft;
|
|
59
|
+
useImperativeHandle(ref, () => triggerRef.current);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (open) {
|
|
62
|
+
const p = parseTime(value);
|
|
63
|
+
if (p) setDraft(p);
|
|
64
|
+
}
|
|
65
|
+
}, [open, value]);
|
|
66
|
+
function commit() {
|
|
67
|
+
const d = draftRef.current;
|
|
68
|
+
const t = `${String(d.h).padStart(2, "0")}:${String(d.m).padStart(2, "0")}`;
|
|
69
|
+
if (min && compareTime(t, min) < 0) return;
|
|
70
|
+
if (max && compareTime(t, max) > 0) return;
|
|
71
|
+
onChange(t);
|
|
72
|
+
}
|
|
73
|
+
function adjust(field, delta) {
|
|
74
|
+
setDraft((d) => {
|
|
75
|
+
if (field === "h") {
|
|
76
|
+
let h = d.h + delta;
|
|
77
|
+
if (h < 0) h = 23;
|
|
78
|
+
if (h > 23) h = 0;
|
|
79
|
+
return __spreadProps(__spreadValues({}, d), { h });
|
|
80
|
+
}
|
|
81
|
+
let m = d.m + delta * step;
|
|
82
|
+
if (m < 0) m = 60 - step;
|
|
83
|
+
if (m >= 60) m = 0;
|
|
84
|
+
return __spreadProps(__spreadValues({}, d), { m: clampMinute(m, step) });
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function handleClear(e) {
|
|
88
|
+
var _a;
|
|
89
|
+
e.stopPropagation();
|
|
90
|
+
onChange(null);
|
|
91
|
+
(_a = triggerRef.current) == null ? void 0 : _a.focus();
|
|
92
|
+
}
|
|
93
|
+
const display = (() => {
|
|
94
|
+
const p = parseTime(value);
|
|
95
|
+
if (!p) return "";
|
|
96
|
+
return formatTime(p.h, p.m, format);
|
|
97
|
+
})();
|
|
98
|
+
const dialog = /* @__PURE__ */ React.createElement(
|
|
99
|
+
"div",
|
|
100
|
+
{
|
|
101
|
+
role: "dialog",
|
|
102
|
+
"aria-label": "Seletor de hora",
|
|
103
|
+
className: "rounded-(--radius-control) border border-stroke-default bg-surface-default shadow-lg p-3"
|
|
104
|
+
},
|
|
105
|
+
/* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement(
|
|
106
|
+
Spinner,
|
|
107
|
+
{
|
|
108
|
+
label: "Hora",
|
|
109
|
+
value: String(draft.h).padStart(2, "0"),
|
|
110
|
+
onUp: () => adjust("h", 1),
|
|
111
|
+
onDown: () => adjust("h", -1)
|
|
112
|
+
}
|
|
113
|
+
), /* @__PURE__ */ React.createElement("span", { className: "text-heading-sm font-semibold text-fg-muted" }, ":"), /* @__PURE__ */ React.createElement(
|
|
114
|
+
Spinner,
|
|
115
|
+
{
|
|
116
|
+
label: "Minuto",
|
|
117
|
+
value: String(draft.m).padStart(2, "0"),
|
|
118
|
+
onUp: () => adjust("m", 1),
|
|
119
|
+
onDown: () => adjust("m", -1)
|
|
120
|
+
}
|
|
121
|
+
), format === "12h" && /* @__PURE__ */ React.createElement("span", { className: "text-caption font-medium text-fg-secondary ml-1" }, draft.h >= 12 ? "PM" : "AM")),
|
|
122
|
+
/* @__PURE__ */ React.createElement("div", { className: "flex justify-end gap-2 mt-3" }, /* @__PURE__ */ React.createElement(
|
|
123
|
+
"button",
|
|
124
|
+
{
|
|
125
|
+
type: "button",
|
|
126
|
+
onClick: () => setOpen(false),
|
|
127
|
+
className: "text-caption text-fg-muted hover:text-fg-primary transition-colors px-2 py-1"
|
|
128
|
+
},
|
|
129
|
+
"Cancelar"
|
|
130
|
+
), /* @__PURE__ */ React.createElement(
|
|
131
|
+
"button",
|
|
132
|
+
{
|
|
133
|
+
type: "button",
|
|
134
|
+
onClick: () => {
|
|
135
|
+
commit();
|
|
136
|
+
setOpen(false);
|
|
137
|
+
},
|
|
138
|
+
className: "text-caption font-medium bg-brand-primary text-brand-on-primary px-3 py-1 rounded transition-colors hover:bg-brand-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-stroke-focus"
|
|
139
|
+
},
|
|
140
|
+
"OK"
|
|
141
|
+
))
|
|
142
|
+
);
|
|
143
|
+
return /* @__PURE__ */ React.createElement("div", { className: ["relative", width === "full" ? "block w-full" : "inline-block", className].join(" ") }, /* @__PURE__ */ React.createElement(
|
|
144
|
+
Popover,
|
|
145
|
+
{
|
|
146
|
+
trigger: /* @__PURE__ */ React.createElement(
|
|
147
|
+
"button",
|
|
148
|
+
{
|
|
149
|
+
ref: triggerRef,
|
|
150
|
+
type: "button",
|
|
151
|
+
onClick: (e) => {
|
|
152
|
+
e.stopPropagation();
|
|
153
|
+
if (!disabled) setOpen((o) => !o);
|
|
154
|
+
},
|
|
155
|
+
disabled,
|
|
156
|
+
"aria-label": ariaLabel != null ? ariaLabel : "Selecionar hora",
|
|
157
|
+
"aria-haspopup": "dialog",
|
|
158
|
+
"aria-expanded": open,
|
|
159
|
+
className: [
|
|
160
|
+
"w-full flex items-center gap-2 rounded-(--radius-control) border border-stroke-default bg-surface-default",
|
|
161
|
+
"transition-colors focus:outline-none focus:border-stroke-focus focus:ring-2 focus:ring-stroke-focus/20",
|
|
162
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
163
|
+
value ? "pr-7" : "",
|
|
164
|
+
SIZE_CLASS[size]
|
|
165
|
+
].join(" ")
|
|
166
|
+
},
|
|
167
|
+
/* @__PURE__ */ React.createElement(Clock, { size: 16, className: "text-fg-muted shrink-0" }),
|
|
168
|
+
/* @__PURE__ */ React.createElement("span", { className: ["flex-1 text-left truncate", display ? "text-fg-primary" : "text-fg-placeholder"].join(" ") }, display || placeholder)
|
|
169
|
+
),
|
|
170
|
+
triggerClassName: width === "full" ? "block w-full" : "inline-block",
|
|
171
|
+
placement: "bottom-start",
|
|
172
|
+
offset: 4,
|
|
173
|
+
open,
|
|
174
|
+
onOpenChange: (v) => {
|
|
175
|
+
if (!disabled) setOpen(v);
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
() => dialog
|
|
179
|
+
), value && !disabled && /* @__PURE__ */ React.createElement(
|
|
180
|
+
"button",
|
|
181
|
+
{
|
|
182
|
+
type: "button",
|
|
183
|
+
onClick: handleClear,
|
|
184
|
+
"aria-label": "Limpar hora",
|
|
185
|
+
className: "absolute right-2 top-1/2 -translate-y-1/2 text-fg-muted hover:text-fg-primary p-0.5 rounded transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-stroke-focus"
|
|
186
|
+
},
|
|
187
|
+
/* @__PURE__ */ React.createElement(X, { size: 14 })
|
|
188
|
+
));
|
|
189
|
+
});
|
|
190
|
+
function Spinner({ label, value, onUp, onDown }) {
|
|
191
|
+
return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col items-center", role: "group", "aria-label": label }, /* @__PURE__ */ React.createElement(
|
|
192
|
+
"button",
|
|
193
|
+
{
|
|
194
|
+
type: "button",
|
|
195
|
+
onClick: onUp,
|
|
196
|
+
"aria-label": `Aumentar ${label.toLowerCase()}`,
|
|
197
|
+
className: "p-0.5 rounded hover:bg-surface-raised text-fg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-stroke-focus"
|
|
198
|
+
},
|
|
199
|
+
/* @__PURE__ */ React.createElement(ChevronUp, { size: 16 })
|
|
200
|
+
), /* @__PURE__ */ React.createElement("div", { className: "px-2 py-1 text-heading-lg font-mono font-semibold text-fg-primary tabular-nums select-none min-w-[3ch] text-center" }, value), /* @__PURE__ */ React.createElement(
|
|
201
|
+
"button",
|
|
202
|
+
{
|
|
203
|
+
type: "button",
|
|
204
|
+
onClick: onDown,
|
|
205
|
+
"aria-label": `Diminuir ${label.toLowerCase()}`,
|
|
206
|
+
className: "p-0.5 rounded hover:bg-surface-raised text-fg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-stroke-focus"
|
|
207
|
+
},
|
|
208
|
+
/* @__PURE__ */ React.createElement(ChevronDown, { size: 16 })
|
|
209
|
+
));
|
|
210
|
+
}
|
|
211
|
+
export {
|
|
212
|
+
TimePicker
|
|
213
|
+
};
|