@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,19 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Dropzone — área de arrastar-e-soltar / clicar para selecionar arquivos.
|
|
6
|
+
* Substitui `<div className="border-2 border-dashed rounded-xl" onDrop=...>` reimplementado.
|
|
7
|
+
* Gerencia estado de drag, input file escondido e clique. O conteúdo (ícone + texto) é livre.
|
|
8
|
+
*/
|
|
9
|
+
interface DropzoneProps {
|
|
10
|
+
onFiles: (files: FileList) => void;
|
|
11
|
+
accept?: string;
|
|
12
|
+
multiple?: boolean;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
className?: string;
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
declare function Dropzone({ onFiles, accept, multiple, disabled, className, children }: DropzoneProps): react.JSX.Element;
|
|
18
|
+
|
|
19
|
+
export { Dropzone, type DropzoneProps };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../chunk-ORMEWXMH.js";
|
|
3
|
+
import { useRef, useState } from "react";
|
|
4
|
+
function Dropzone({ onFiles, accept, multiple = false, disabled = false, className = "", children }) {
|
|
5
|
+
const inputRef = useRef(null);
|
|
6
|
+
const [dragging, setDragging] = useState(false);
|
|
7
|
+
function handleDrop(e) {
|
|
8
|
+
var _a;
|
|
9
|
+
e.preventDefault();
|
|
10
|
+
setDragging(false);
|
|
11
|
+
if (disabled) return;
|
|
12
|
+
if ((_a = e.dataTransfer.files) == null ? void 0 : _a.length) onFiles(e.dataTransfer.files);
|
|
13
|
+
}
|
|
14
|
+
return /* @__PURE__ */ React.createElement(
|
|
15
|
+
"div",
|
|
16
|
+
{
|
|
17
|
+
role: "button",
|
|
18
|
+
tabIndex: disabled ? -1 : 0,
|
|
19
|
+
onClick: () => {
|
|
20
|
+
var _a;
|
|
21
|
+
return !disabled && ((_a = inputRef.current) == null ? void 0 : _a.click());
|
|
22
|
+
},
|
|
23
|
+
onKeyDown: (e) => {
|
|
24
|
+
var _a;
|
|
25
|
+
if (!disabled && (e.key === "Enter" || e.key === " ")) {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
(_a = inputRef.current) == null ? void 0 : _a.click();
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
onDragOver: (e) => {
|
|
31
|
+
e.preventDefault();
|
|
32
|
+
if (!disabled) setDragging(true);
|
|
33
|
+
},
|
|
34
|
+
onDragLeave: () => setDragging(false),
|
|
35
|
+
onDrop: handleDrop,
|
|
36
|
+
className: [
|
|
37
|
+
"flex flex-col items-center justify-center gap-3 rounded-(--radius-card) border-2 border-dashed py-10 transition-colors",
|
|
38
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-stroke-focus",
|
|
39
|
+
disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer",
|
|
40
|
+
dragging ? "border-stroke-focus bg-surface-raised" : "border-stroke-control hover:border-stroke-strong hover:bg-surface-page",
|
|
41
|
+
className
|
|
42
|
+
].filter(Boolean).join(" ")
|
|
43
|
+
},
|
|
44
|
+
/* @__PURE__ */ React.createElement(
|
|
45
|
+
"input",
|
|
46
|
+
{
|
|
47
|
+
ref: inputRef,
|
|
48
|
+
type: "file",
|
|
49
|
+
accept,
|
|
50
|
+
multiple,
|
|
51
|
+
disabled,
|
|
52
|
+
className: "hidden",
|
|
53
|
+
onChange: (e) => {
|
|
54
|
+
var _a;
|
|
55
|
+
if ((_a = e.target.files) == null ? void 0 : _a.length) onFiles(e.target.files);
|
|
56
|
+
e.target.value = "";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
children
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
export {
|
|
64
|
+
Dropzone
|
|
65
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import * as lucide_react from 'lucide-react';
|
|
4
|
+
|
|
5
|
+
declare const ICON_MAP: {
|
|
6
|
+
readonly box: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
7
|
+
readonly service: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
8
|
+
readonly kit: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
9
|
+
readonly input: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
10
|
+
readonly order: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
11
|
+
readonly customer: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
12
|
+
readonly finance: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
13
|
+
readonly schedule: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
14
|
+
readonly inventory: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
15
|
+
readonly price: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
16
|
+
readonly category: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
17
|
+
readonly generic: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
18
|
+
readonly search: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
19
|
+
readonly lock: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
20
|
+
readonly catalog: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
21
|
+
readonly channels: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
22
|
+
readonly commercial: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
23
|
+
readonly operation: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
24
|
+
readonly intelligence: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
25
|
+
readonly billing: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
26
|
+
};
|
|
27
|
+
type EmptyStateIcon = keyof typeof ICON_MAP;
|
|
28
|
+
interface EmptyStateCta {
|
|
29
|
+
label: string;
|
|
30
|
+
href?: string;
|
|
31
|
+
onClick?: () => void;
|
|
32
|
+
}
|
|
33
|
+
interface EmptyStateProps {
|
|
34
|
+
icon?: EmptyStateIcon;
|
|
35
|
+
title: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
cta?: EmptyStateCta;
|
|
38
|
+
/**
|
|
39
|
+
* full = fills available height (use inside page containers)
|
|
40
|
+
* compact = inline fit with vertical padding
|
|
41
|
+
*/
|
|
42
|
+
size?: 'full' | 'compact';
|
|
43
|
+
children?: ReactNode;
|
|
44
|
+
className?: string;
|
|
45
|
+
}
|
|
46
|
+
declare function EmptyState({ icon, title, description, cta, size, children, className, }: EmptyStateProps): react.JSX.Element;
|
|
47
|
+
|
|
48
|
+
export { EmptyState, type EmptyStateCta, type EmptyStateIcon, type EmptyStateProps, ICON_MAP };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../chunk-ORMEWXMH.js";
|
|
3
|
+
import {
|
|
4
|
+
Package,
|
|
5
|
+
Clock,
|
|
6
|
+
Combine,
|
|
7
|
+
Boxes,
|
|
8
|
+
FileText,
|
|
9
|
+
Users,
|
|
10
|
+
Wallet,
|
|
11
|
+
CalendarDays,
|
|
12
|
+
Warehouse,
|
|
13
|
+
Tag,
|
|
14
|
+
LayoutGrid,
|
|
15
|
+
Info,
|
|
16
|
+
SearchX,
|
|
17
|
+
Lock,
|
|
18
|
+
Send,
|
|
19
|
+
HandCoins,
|
|
20
|
+
Store,
|
|
21
|
+
BarChart3,
|
|
22
|
+
CreditCard
|
|
23
|
+
} from "lucide-react";
|
|
24
|
+
const ICON_MAP = {
|
|
25
|
+
box: Package,
|
|
26
|
+
service: Clock,
|
|
27
|
+
kit: Combine,
|
|
28
|
+
input: Boxes,
|
|
29
|
+
order: FileText,
|
|
30
|
+
customer: Users,
|
|
31
|
+
finance: Wallet,
|
|
32
|
+
schedule: CalendarDays,
|
|
33
|
+
inventory: Warehouse,
|
|
34
|
+
price: Tag,
|
|
35
|
+
category: LayoutGrid,
|
|
36
|
+
generic: Info,
|
|
37
|
+
search: SearchX,
|
|
38
|
+
lock: Lock,
|
|
39
|
+
// Categorias de feature (Paywall) ──
|
|
40
|
+
catalog: Package,
|
|
41
|
+
channels: Send,
|
|
42
|
+
commercial: HandCoins,
|
|
43
|
+
operation: Store,
|
|
44
|
+
intelligence: BarChart3,
|
|
45
|
+
billing: CreditCard
|
|
46
|
+
};
|
|
47
|
+
function EmptyState({
|
|
48
|
+
icon = "generic",
|
|
49
|
+
title,
|
|
50
|
+
description,
|
|
51
|
+
cta,
|
|
52
|
+
size = "full",
|
|
53
|
+
children,
|
|
54
|
+
className = ""
|
|
55
|
+
}) {
|
|
56
|
+
const Icon = ICON_MAP[icon];
|
|
57
|
+
return /* @__PURE__ */ React.createElement(
|
|
58
|
+
"div",
|
|
59
|
+
{
|
|
60
|
+
className: [
|
|
61
|
+
"flex flex-col items-center justify-center text-center px-6",
|
|
62
|
+
size === "full" ? "min-h-[320px] flex-1" : "min-h-[200px] py-10",
|
|
63
|
+
className
|
|
64
|
+
].filter(Boolean).join(" ")
|
|
65
|
+
},
|
|
66
|
+
/* @__PURE__ */ React.createElement("div", { className: "mb-5 text-stroke-strong" }, /* @__PURE__ */ React.createElement(Icon, { size: 72, strokeWidth: 1.25 })),
|
|
67
|
+
/* @__PURE__ */ React.createElement("p", { className: "text-body font-semibold text-fg-primary mb-2" }, title),
|
|
68
|
+
description && /* @__PURE__ */ React.createElement("p", { className: "text-label text-fg-muted max-w-sm leading-relaxed mb-4" }, description),
|
|
69
|
+
cta && (cta.href ? /* @__PURE__ */ React.createElement(
|
|
70
|
+
"a",
|
|
71
|
+
{
|
|
72
|
+
href: cta.href,
|
|
73
|
+
className: "mt-3 inline-block px-4 py-2 text-label font-medium rounded-(--radius-card) transition-colors text-brand-on-primary bg-brand-primary hover:bg-brand-hover"
|
|
74
|
+
},
|
|
75
|
+
cta.label
|
|
76
|
+
) : /* @__PURE__ */ React.createElement(
|
|
77
|
+
"button",
|
|
78
|
+
{
|
|
79
|
+
type: "button",
|
|
80
|
+
onClick: cta.onClick,
|
|
81
|
+
className: "mt-3 inline-block px-4 py-2 text-label font-medium rounded-(--radius-card) transition-colors text-brand-on-primary bg-brand-primary hover:bg-brand-hover"
|
|
82
|
+
},
|
|
83
|
+
cta.label
|
|
84
|
+
)),
|
|
85
|
+
children
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
export {
|
|
89
|
+
EmptyState,
|
|
90
|
+
ICON_MAP
|
|
91
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type FABConfig = {
|
|
5
|
+
label: string;
|
|
6
|
+
href?: string;
|
|
7
|
+
onClick?: () => void;
|
|
8
|
+
/** cta = primary action button | save = saving-bar with primary + secondary */
|
|
9
|
+
variant?: 'cta' | 'save';
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
secondary?: {
|
|
13
|
+
label: string;
|
|
14
|
+
onClick: () => void;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
type FABContextValue = {
|
|
18
|
+
config: FABConfig | null;
|
|
19
|
+
setFAB: (config: FABConfig) => void;
|
|
20
|
+
clearFAB: () => void;
|
|
21
|
+
bottomOffset: number;
|
|
22
|
+
setBottomOffset: (n: number) => void;
|
|
23
|
+
fabHidden: boolean;
|
|
24
|
+
setFabHidden: (v: boolean) => void;
|
|
25
|
+
};
|
|
26
|
+
declare function FABProvider({ children }: {
|
|
27
|
+
children: ReactNode;
|
|
28
|
+
}): react.JSX.Element;
|
|
29
|
+
declare function useFAB(): FABContextValue;
|
|
30
|
+
/**
|
|
31
|
+
* Register the page's primary FAB action.
|
|
32
|
+
* Clears the FAB automatically on unmount.
|
|
33
|
+
* Pass a stable deps array to avoid re-registering on every render.
|
|
34
|
+
*/
|
|
35
|
+
declare function usePageFAB(config: FABConfig | null, deps?: unknown[]): void;
|
|
36
|
+
declare function FABRoot(): react.JSX.Element;
|
|
37
|
+
|
|
38
|
+
export { type FABConfig, FABProvider, FABRoot, useFAB, usePageFAB };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../chunk-ORMEWXMH.js";
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
useCallback,
|
|
6
|
+
useContext,
|
|
7
|
+
useEffect,
|
|
8
|
+
useRef,
|
|
9
|
+
useState
|
|
10
|
+
} from "react";
|
|
11
|
+
import Link from "next/link";
|
|
12
|
+
import { Plus, Loader2 } from "lucide-react";
|
|
13
|
+
import { useSavingBarActive } from "./saving-bar-context.js";
|
|
14
|
+
const FABContext = createContext({
|
|
15
|
+
config: null,
|
|
16
|
+
setFAB: () => {
|
|
17
|
+
},
|
|
18
|
+
clearFAB: () => {
|
|
19
|
+
},
|
|
20
|
+
bottomOffset: 0,
|
|
21
|
+
setBottomOffset: () => {
|
|
22
|
+
},
|
|
23
|
+
fabHidden: false,
|
|
24
|
+
setFabHidden: () => {
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
function FABProvider({ children }) {
|
|
28
|
+
const [config, setConfig] = useState(null);
|
|
29
|
+
const [bottomOffset, setBottomOffset] = useState(0);
|
|
30
|
+
const [fabHidden, setFabHidden] = useState(false);
|
|
31
|
+
const setFAB = useCallback((cfg) => setConfig(cfg), []);
|
|
32
|
+
const clearFAB = useCallback(() => setConfig(null), []);
|
|
33
|
+
return /* @__PURE__ */ React.createElement(FABContext.Provider, { value: { config, setFAB, clearFAB, bottomOffset, setBottomOffset, fabHidden, setFabHidden } }, children);
|
|
34
|
+
}
|
|
35
|
+
function useFAB() {
|
|
36
|
+
return useContext(FABContext);
|
|
37
|
+
}
|
|
38
|
+
function usePageFAB(config, deps = []) {
|
|
39
|
+
const { setFAB, clearFAB } = useFAB();
|
|
40
|
+
const configRef = useRef(config);
|
|
41
|
+
configRef.current = config;
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (configRef.current) {
|
|
44
|
+
setFAB(configRef.current);
|
|
45
|
+
} else {
|
|
46
|
+
clearFAB();
|
|
47
|
+
}
|
|
48
|
+
return () => clearFAB();
|
|
49
|
+
}, [setFAB, clearFAB, ...deps]);
|
|
50
|
+
}
|
|
51
|
+
function FABRoot() {
|
|
52
|
+
const { config, bottomOffset, fabHidden } = useFAB();
|
|
53
|
+
const savingBarActive = useSavingBarActive();
|
|
54
|
+
const hiddenByBar = savingBarActive && (config == null ? void 0 : config.variant) !== "save";
|
|
55
|
+
const visible = !!config && !fabHidden && !hiddenByBar;
|
|
56
|
+
const wrapCls = [
|
|
57
|
+
"fixed right-6 z-40 flex items-center gap-2 transition-all duration-200",
|
|
58
|
+
visible ? "opacity-100 translate-y-0 pointer-events-auto" : "opacity-0 translate-y-2 pointer-events-none"
|
|
59
|
+
].join(" ");
|
|
60
|
+
const bottomStyle = { bottom: `${24 + bottomOffset}px` };
|
|
61
|
+
if ((config == null ? void 0 : config.variant) === "save") {
|
|
62
|
+
return /* @__PURE__ */ React.createElement("div", { className: wrapCls, style: bottomStyle }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-3 rounded-(--radius-control) px-4 py-3 [background:var(--fab-save-bg)] [box-shadow:var(--fab-save-shadow)]" }, config.secondary && /* @__PURE__ */ React.createElement(
|
|
63
|
+
"button",
|
|
64
|
+
{
|
|
65
|
+
type: "button",
|
|
66
|
+
onClick: config.secondary.onClick,
|
|
67
|
+
disabled: config.loading,
|
|
68
|
+
className: "rounded-(--radius-control) border px-3 py-1.5 text-label font-medium transition-colors disabled:opacity-40 cursor-pointer [border-color:var(--fab-save-discard-border)] [color:var(--fab-save-discard-text)] hover:[border-color:var(--fab-save-discard-border-hover)] hover:[color:var(--fab-save-discard-text-hover)]"
|
|
69
|
+
},
|
|
70
|
+
config.secondary.label
|
|
71
|
+
), /* @__PURE__ */ React.createElement(
|
|
72
|
+
"button",
|
|
73
|
+
{
|
|
74
|
+
type: "button",
|
|
75
|
+
onClick: config.onClick,
|
|
76
|
+
disabled: config.disabled || config.loading,
|
|
77
|
+
className: "rounded-(--radius-control) px-4 py-1.5 text-label font-medium transition-colors disabled:opacity-50 cursor-pointer flex items-center gap-2 [background:var(--fab-save-primary-bg)] [color:var(--fab-save-primary-text)] hover:[background:var(--fab-save-primary-bg-hover)]"
|
|
78
|
+
},
|
|
79
|
+
config.loading ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Loader2, { className: "w-4 h-4 animate-spin" }), "Salvando...") : config.label
|
|
80
|
+
)));
|
|
81
|
+
}
|
|
82
|
+
const btnCls = "flex items-center gap-2 h-12 pl-4 pr-5 rounded-(--radius-control) text-label font-semibold shadow-lg transition-colors cursor-pointer [background:var(--fab-cta-bg)] [color:var(--fab-cta-text)] hover:[background:var(--fab-cta-bg-hover)]";
|
|
83
|
+
return /* @__PURE__ */ React.createElement("div", { className: wrapCls, style: bottomStyle }, (config == null ? void 0 : config.href) ? /* @__PURE__ */ React.createElement(Link, { href: config.href, className: btnCls }, /* @__PURE__ */ React.createElement(Plus, { size: 16, strokeWidth: 2.5 }), config == null ? void 0 : config.label) : /* @__PURE__ */ React.createElement(
|
|
84
|
+
"button",
|
|
85
|
+
{
|
|
86
|
+
type: "button",
|
|
87
|
+
onClick: config == null ? void 0 : config.onClick,
|
|
88
|
+
disabled: config == null ? void 0 : config.disabled,
|
|
89
|
+
className: btnCls + " disabled:opacity-50"
|
|
90
|
+
},
|
|
91
|
+
/* @__PURE__ */ React.createElement(Plus, { size: 16, strokeWidth: 2.5 }),
|
|
92
|
+
config == null ? void 0 : config.label
|
|
93
|
+
));
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
FABProvider,
|
|
97
|
+
FABRoot,
|
|
98
|
+
useFAB,
|
|
99
|
+
usePageFAB
|
|
100
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
interface FilterChipBaseProps {
|
|
4
|
+
label: string;
|
|
5
|
+
active: boolean;
|
|
6
|
+
count?: number;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
interface FilterChipLinkProps extends FilterChipBaseProps {
|
|
11
|
+
href: string;
|
|
12
|
+
onClick?: never;
|
|
13
|
+
}
|
|
14
|
+
interface FilterChipButtonProps extends FilterChipBaseProps {
|
|
15
|
+
onClick: () => void;
|
|
16
|
+
href?: never;
|
|
17
|
+
}
|
|
18
|
+
type FilterChipProps = FilterChipLinkProps | FilterChipButtonProps;
|
|
19
|
+
declare function FilterChip({ label, active, count, disabled, href, onClick, className }: FilterChipProps): react.JSX.Element;
|
|
20
|
+
type FilterChipItem = {
|
|
21
|
+
label: string;
|
|
22
|
+
value: string | undefined;
|
|
23
|
+
count?: number;
|
|
24
|
+
href?: string;
|
|
25
|
+
onClick?: () => void;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
};
|
|
28
|
+
interface FilterChipGroupProps {
|
|
29
|
+
items: FilterChipItem[];
|
|
30
|
+
active: string | undefined;
|
|
31
|
+
label: string;
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* FilterChipGroup — barra de filtro com pills.
|
|
36
|
+
*
|
|
37
|
+
* Regra: ≤ 5 opções. Mais que isso → usar Select.
|
|
38
|
+
* Renderiza como links (href) para preservar URL e back/forward,
|
|
39
|
+
* ou como buttons (onClick) para filtro client-side.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* <FilterChipGroup
|
|
43
|
+
* label="Filtrar por tipo"
|
|
44
|
+
* items={[
|
|
45
|
+
* { label: 'Todos', value: undefined, href: '/stock' },
|
|
46
|
+
* { label: 'Entradas', value: 'in', href: '/stock?filter=in' },
|
|
47
|
+
* { label: 'Saídas', value: 'out', href: '/stock?filter=out' },
|
|
48
|
+
* ]}
|
|
49
|
+
* active={searchParams.filter}
|
|
50
|
+
* />
|
|
51
|
+
*/
|
|
52
|
+
declare function FilterChipGroup({ items, active, label, className }: FilterChipGroupProps): react.JSX.Element;
|
|
53
|
+
|
|
54
|
+
export { FilterChip, FilterChipGroup, type FilterChipGroupProps, type FilterChipItem, type FilterChipProps };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../chunk-ORMEWXMH.js";
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
const BASE = "h-control-sm inline-flex items-center text-caption font-medium border transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-stroke-focus px-[var(--filter-chip-padding-x)] [border-radius:var(--filter-chip-radius)]";
|
|
5
|
+
const ACTIVE = "[background:var(--filter-chip-color-surface-active)] [border-color:var(--filter-chip-color-stroke-active)] [color:var(--filter-chip-color-text-active)]";
|
|
6
|
+
const INACTIVE = "[background:var(--filter-chip-color-surface-inactive)] [border-color:var(--filter-chip-color-stroke-inactive)] [color:var(--filter-chip-color-text-inactive)] hover:[background:var(--filter-chip-color-surface-hover)] hover:[border-color:var(--filter-chip-color-stroke-hover)] hover:[color:var(--filter-chip-color-text-hover)]";
|
|
7
|
+
const DISABLED = "[background:var(--filter-chip-color-surface-disabled)] [border-color:var(--filter-chip-color-stroke-disabled)] [color:var(--filter-chip-color-text-disabled)] opacity-50 pointer-events-none cursor-not-allowed";
|
|
8
|
+
function FilterChipBody({ label, count }) {
|
|
9
|
+
if (count === void 0) return /* @__PURE__ */ React.createElement(React.Fragment, null, label);
|
|
10
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, label, /* @__PURE__ */ React.createElement("span", { className: "ml-1 opacity-60 tabular-nums" }, count));
|
|
11
|
+
}
|
|
12
|
+
function FilterChip({ label, active, count, disabled = false, href, onClick, className = "" }) {
|
|
13
|
+
const cls = [BASE, active ? ACTIVE : INACTIVE, disabled ? DISABLED : "", className].filter(Boolean).join(" ");
|
|
14
|
+
if (href) {
|
|
15
|
+
return /* @__PURE__ */ React.createElement(
|
|
16
|
+
Link,
|
|
17
|
+
{
|
|
18
|
+
href,
|
|
19
|
+
"aria-current": active ? "true" : void 0,
|
|
20
|
+
"aria-disabled": disabled || void 0,
|
|
21
|
+
tabIndex: disabled ? -1 : void 0,
|
|
22
|
+
className: cls
|
|
23
|
+
},
|
|
24
|
+
/* @__PURE__ */ React.createElement(FilterChipBody, { label, count })
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return /* @__PURE__ */ React.createElement(
|
|
28
|
+
"button",
|
|
29
|
+
{
|
|
30
|
+
type: "button",
|
|
31
|
+
onClick,
|
|
32
|
+
"aria-pressed": active,
|
|
33
|
+
disabled,
|
|
34
|
+
className: cls
|
|
35
|
+
},
|
|
36
|
+
/* @__PURE__ */ React.createElement(FilterChipBody, { label, count })
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
function FilterChipGroup({ items, active, label, className = "" }) {
|
|
40
|
+
return /* @__PURE__ */ React.createElement("div", { role: "group", "aria-label": label, className: ["flex flex-wrap [gap:var(--filter-chip-group-gap)]", className].filter(Boolean).join(" ") }, items.map((item) => {
|
|
41
|
+
var _a;
|
|
42
|
+
if (process.env.NODE_ENV === "development" && !item.href && !item.onClick) {
|
|
43
|
+
console.warn(`[FilterChipGroup] item "${item.label}" has neither href nor onClick \u2014 click will have no effect`);
|
|
44
|
+
}
|
|
45
|
+
const isActive = active === item.value || !active && item.value === void 0;
|
|
46
|
+
if (item.href) {
|
|
47
|
+
return /* @__PURE__ */ React.createElement(FilterChip, { key: item.label, label: item.label, active: isActive, count: item.count, disabled: item.disabled, href: item.href });
|
|
48
|
+
}
|
|
49
|
+
return /* @__PURE__ */ React.createElement(
|
|
50
|
+
FilterChip,
|
|
51
|
+
{
|
|
52
|
+
key: item.label,
|
|
53
|
+
label: item.label,
|
|
54
|
+
active: isActive,
|
|
55
|
+
count: item.count,
|
|
56
|
+
disabled: item.disabled,
|
|
57
|
+
onClick: (_a = item.onClick) != null ? _a : (() => {
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
export {
|
|
64
|
+
FilterChip,
|
|
65
|
+
FilterChipGroup
|
|
66
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* FloatingStepper — pill flutuante de etapas de um fluxo (PDV, checkout).
|
|
6
|
+
*
|
|
7
|
+
* Mostra as etapas com dot de estado; etapas anteriores são navegáveis
|
|
8
|
+
* (volta no fluxo), futuras ficam desabilitadas. `canNavigate` permite
|
|
9
|
+
* customizar a regra. Slot `action` pra ação terminal (ex.: Reset).
|
|
10
|
+
*
|
|
11
|
+
* O POSICIONAMENTO é do caller (absolute/fixed via wrapper ou className) —
|
|
12
|
+
* o componente só renderiza a pill.
|
|
13
|
+
*
|
|
14
|
+
* Uso:
|
|
15
|
+
* <FloatingStepper
|
|
16
|
+
* steps={[{ key: 'cart', label: 'Carrinho' }, ...]}
|
|
17
|
+
* current={step}
|
|
18
|
+
* onNavigate={setStep}
|
|
19
|
+
* action={{ label: 'Reset', icon: <RotateCcw />, onClick: reset }}
|
|
20
|
+
* className="absolute bottom-3 left-1/2 -translate-x-1/2 z-30"
|
|
21
|
+
* />
|
|
22
|
+
*/
|
|
23
|
+
type FloatingStepperStep = {
|
|
24
|
+
key: string;
|
|
25
|
+
label: string;
|
|
26
|
+
};
|
|
27
|
+
interface FloatingStepperProps {
|
|
28
|
+
steps: FloatingStepperStep[];
|
|
29
|
+
/** key da etapa atual */
|
|
30
|
+
current: string;
|
|
31
|
+
onNavigate?: (key: string) => void;
|
|
32
|
+
/** Regra de navegação por etapa. Default: só etapas anteriores à atual. */
|
|
33
|
+
canNavigate?: (key: string, index: number, currentIndex: number) => boolean;
|
|
34
|
+
/** Ação à direita, separada por divisor (ex.: Reset). */
|
|
35
|
+
action?: {
|
|
36
|
+
label: string;
|
|
37
|
+
icon?: ReactNode;
|
|
38
|
+
onClick: () => void;
|
|
39
|
+
};
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
declare function FloatingStepper({ steps, current, onNavigate, canNavigate, action, className, }: FloatingStepperProps): react.JSX.Element;
|
|
43
|
+
|
|
44
|
+
export { FloatingStepper, type FloatingStepperProps, type FloatingStepperStep };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../chunk-ORMEWXMH.js";
|
|
3
|
+
function FloatingStepper({
|
|
4
|
+
steps,
|
|
5
|
+
current,
|
|
6
|
+
onNavigate,
|
|
7
|
+
canNavigate,
|
|
8
|
+
action,
|
|
9
|
+
className = ""
|
|
10
|
+
}) {
|
|
11
|
+
const currentIdx = steps.findIndex((s) => s.key === current);
|
|
12
|
+
return /* @__PURE__ */ React.createElement(
|
|
13
|
+
"div",
|
|
14
|
+
{
|
|
15
|
+
className: [
|
|
16
|
+
"flex items-center gap-0.5 rounded-full bg-surface-shell shadow-2xl px-1.5 py-1.5",
|
|
17
|
+
className
|
|
18
|
+
].filter(Boolean).join(" ")
|
|
19
|
+
},
|
|
20
|
+
steps.map((s, idx) => {
|
|
21
|
+
const isCurrent = idx === currentIdx;
|
|
22
|
+
const canGo = canNavigate ? canNavigate(s.key, idx, currentIdx) : idx < currentIdx;
|
|
23
|
+
return /* @__PURE__ */ React.createElement(
|
|
24
|
+
"button",
|
|
25
|
+
{
|
|
26
|
+
key: s.key,
|
|
27
|
+
type: "button",
|
|
28
|
+
disabled: !canGo && !isCurrent,
|
|
29
|
+
"aria-current": isCurrent ? "step" : void 0,
|
|
30
|
+
onClick: () => {
|
|
31
|
+
if (canGo) onNavigate == null ? void 0 : onNavigate(s.key);
|
|
32
|
+
},
|
|
33
|
+
className: `flex items-center gap-1.5 rounded-full px-3 py-1.5 text-caption font-medium whitespace-nowrap transition-colors ${isCurrent ? "bg-(--surface-default) text-(--text-primary)" : canGo ? "text-on-shell-muted hover:text-on-shell" : "text-on-shell-subtle cursor-default"}`
|
|
34
|
+
},
|
|
35
|
+
/* @__PURE__ */ React.createElement("span", { className: `w-1.5 h-1.5 rounded-full shrink-0 ${isCurrent ? "bg-(--text-primary)" : "bg-on-shell-subtle"}` }),
|
|
36
|
+
s.label
|
|
37
|
+
);
|
|
38
|
+
}),
|
|
39
|
+
action && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", { className: "w-px h-4 bg-on-shell-line mx-1", "aria-hidden": true }), /* @__PURE__ */ React.createElement(
|
|
40
|
+
"button",
|
|
41
|
+
{
|
|
42
|
+
type: "button",
|
|
43
|
+
onClick: action.onClick,
|
|
44
|
+
className: "flex items-center gap-1.5 rounded-full px-3 py-1.5 text-caption font-medium text-on-shell-muted hover:text-on-shell transition-colors whitespace-nowrap [&_svg]:w-3 [&_svg]:h-3 [&_svg]:shrink-0"
|
|
45
|
+
},
|
|
46
|
+
action.icon,
|
|
47
|
+
action.label
|
|
48
|
+
))
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
FloatingStepper
|
|
53
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface FormCardHeaderProps {
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
title: ReactNode;
|
|
7
|
+
subtitle?: ReactNode;
|
|
8
|
+
/** Slot à direita (ação, badge) — alinhado ao centro vertical do bloco. */
|
|
9
|
+
action?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
declare function FormCardHeader({ icon, title, subtitle, action }: FormCardHeaderProps): react.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { FormCardHeader, type FormCardHeaderProps };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../chunk-ORMEWXMH.js";
|
|
3
|
+
function FormCardHeader({ icon, title, subtitle, action }) {
|
|
4
|
+
return /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-3 pb-3" }, icon && /* @__PURE__ */ React.createElement("span", { className: "grid place-items-center shrink-0 size-9 rounded-(--radius-card) bg-brand-primary text-brand-on-primary" }, icon), /* @__PURE__ */ React.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ React.createElement("p", { className: "text-label font-semibold text-(--text-primary)" }, title), subtitle && /* @__PURE__ */ React.createElement("p", { className: "text-caption text-(--text-muted) mt-1 leading-snug" }, subtitle)), action && /* @__PURE__ */ React.createElement("div", { className: "shrink-0" }, action));
|
|
5
|
+
}
|
|
6
|
+
export {
|
|
7
|
+
FormCardHeader
|
|
8
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type IconButtonVariant = 'filled' | 'outline' | 'ghost';
|
|
5
|
+
type IconButtonColor = 'primary' | 'secondary' | 'danger' | 'neutral';
|
|
6
|
+
type IconButtonSize = 'sm' | 'md' | 'lg';
|
|
7
|
+
interface IconButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
|
|
8
|
+
icon: ReactNode;
|
|
9
|
+
'aria-label': string;
|
|
10
|
+
variant?: IconButtonVariant;
|
|
11
|
+
color?: IconButtonColor;
|
|
12
|
+
size?: IconButtonSize;
|
|
13
|
+
loading?: boolean;
|
|
14
|
+
}
|
|
15
|
+
declare const IconButton: react.ForwardRefExoticComponent<IconButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
16
|
+
|
|
17
|
+
export { IconButton, type IconButtonColor, type IconButtonProps, type IconButtonSize, type IconButtonVariant };
|