@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,33 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { InputHTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
|
|
5
|
+
label?: ReactNode;
|
|
6
|
+
description?: ReactNode;
|
|
7
|
+
error?: string;
|
|
8
|
+
size?: 'sm' | 'md';
|
|
9
|
+
}
|
|
10
|
+
declare const Radio: react.ForwardRefExoticComponent<RadioProps & react.RefAttributes<HTMLInputElement>>;
|
|
11
|
+
interface RadioOption<T extends string = string> {
|
|
12
|
+
value: T;
|
|
13
|
+
label: ReactNode;
|
|
14
|
+
description?: ReactNode;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface RadioGroupProps<T extends string = string> {
|
|
18
|
+
name: string;
|
|
19
|
+
value: T | null;
|
|
20
|
+
onChange: (value: T) => void;
|
|
21
|
+
options: RadioOption<T>[];
|
|
22
|
+
/** Layout. default = vertical. */
|
|
23
|
+
orientation?: 'horizontal' | 'vertical';
|
|
24
|
+
size?: 'sm' | 'md';
|
|
25
|
+
error?: string;
|
|
26
|
+
/** Label do group como `<legend>`. */
|
|
27
|
+
legend?: ReactNode;
|
|
28
|
+
required?: boolean;
|
|
29
|
+
className?: string;
|
|
30
|
+
}
|
|
31
|
+
declare function RadioGroup<T extends string = string>({ name, value, onChange, options, orientation, size, error, legend, required, className, }: RadioGroupProps<T>): react.JSX.Element;
|
|
32
|
+
|
|
33
|
+
export { Radio, RadioGroup, type RadioGroupProps, type RadioOption, type RadioProps };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
__objRest,
|
|
4
|
+
__spreadValues
|
|
5
|
+
} from "../chunk-ORMEWXMH.js";
|
|
6
|
+
import { forwardRef, useId } from "react";
|
|
7
|
+
const SIZE_CLASS = {
|
|
8
|
+
sm: { box: "size-3.5", dot: "size-1.5", label: "text-caption" },
|
|
9
|
+
md: { box: "size-4", dot: "size-2", label: "text-label" }
|
|
10
|
+
};
|
|
11
|
+
const Radio = forwardRef(function Radio2(_a, ref) {
|
|
12
|
+
var _b = _a, { label, description, error, size = "md", className = "", id } = _b, props = __objRest(_b, ["label", "description", "error", "size", "className", "id"]);
|
|
13
|
+
const generatedId = useId();
|
|
14
|
+
const inputId = id != null ? id : generatedId;
|
|
15
|
+
const errId = `${inputId}-error`;
|
|
16
|
+
const sz = SIZE_CLASS[size];
|
|
17
|
+
return /* @__PURE__ */ React.createElement("div", { className: "inline-flex flex-col gap-0.5" }, /* @__PURE__ */ React.createElement(
|
|
18
|
+
"label",
|
|
19
|
+
{
|
|
20
|
+
htmlFor: inputId,
|
|
21
|
+
className: [
|
|
22
|
+
"inline-flex items-start gap-2 cursor-pointer",
|
|
23
|
+
"has-[:disabled]:opacity-50 has-[:disabled]:cursor-not-allowed",
|
|
24
|
+
className
|
|
25
|
+
].filter(Boolean).join(" ")
|
|
26
|
+
},
|
|
27
|
+
/* @__PURE__ */ React.createElement("span", { className: ["relative flex shrink-0 mt-0.5", sz.box].join(" ") }, /* @__PURE__ */ React.createElement(
|
|
28
|
+
"input",
|
|
29
|
+
__spreadValues({
|
|
30
|
+
ref,
|
|
31
|
+
type: "radio",
|
|
32
|
+
id: inputId,
|
|
33
|
+
"aria-invalid": error ? true : void 0,
|
|
34
|
+
"aria-describedby": error ? errId : void 0,
|
|
35
|
+
className: [
|
|
36
|
+
"peer appearance-none rounded-full shrink-0 cursor-pointer",
|
|
37
|
+
sz.box,
|
|
38
|
+
"bg-surface-default",
|
|
39
|
+
error ? "border border-danger checked:border-danger" : "border border-stroke-control checked:border-brand-primary",
|
|
40
|
+
"focus-visible:ring-2 focus-visible:ring-stroke-focus/30 focus-visible:outline-none",
|
|
41
|
+
"disabled:cursor-not-allowed transition-colors"
|
|
42
|
+
].join(" ")
|
|
43
|
+
}, props)
|
|
44
|
+
), /* @__PURE__ */ React.createElement(
|
|
45
|
+
"span",
|
|
46
|
+
{
|
|
47
|
+
"aria-hidden": true,
|
|
48
|
+
className: [
|
|
49
|
+
"absolute inset-0 m-auto rounded-full bg-transparent transition-colors pointer-events-none",
|
|
50
|
+
sz.dot,
|
|
51
|
+
error ? "peer-checked:bg-danger" : "peer-checked:bg-brand-primary"
|
|
52
|
+
].join(" ")
|
|
53
|
+
}
|
|
54
|
+
)),
|
|
55
|
+
(label || description) && /* @__PURE__ */ React.createElement("span", { className: "flex flex-col gap-0.5 select-none" }, label && /* @__PURE__ */ React.createElement("span", { className: [sz.label, "text-fg-primary leading-snug"].join(" ") }, label), description && /* @__PURE__ */ React.createElement("span", { className: "text-caption text-fg-muted leading-snug" }, description))
|
|
56
|
+
), error && /* @__PURE__ */ React.createElement("p", { id: errId, className: [sz.box === "size-3.5" ? "pl-5" : "pl-6", "text-caption text-danger-text"].join(" ") }, error));
|
|
57
|
+
});
|
|
58
|
+
function RadioGroup({
|
|
59
|
+
name,
|
|
60
|
+
value,
|
|
61
|
+
onChange,
|
|
62
|
+
options,
|
|
63
|
+
orientation = "vertical",
|
|
64
|
+
size = "md",
|
|
65
|
+
error,
|
|
66
|
+
legend,
|
|
67
|
+
required,
|
|
68
|
+
className = ""
|
|
69
|
+
}) {
|
|
70
|
+
return /* @__PURE__ */ React.createElement(
|
|
71
|
+
"fieldset",
|
|
72
|
+
{
|
|
73
|
+
className: ["flex flex-col gap-2", className].join(" "),
|
|
74
|
+
"aria-invalid": error ? true : void 0
|
|
75
|
+
},
|
|
76
|
+
legend && /* @__PURE__ */ React.createElement("legend", { className: "text-label font-medium text-fg-primary mb-0.5" }, legend, required && /* @__PURE__ */ React.createElement("span", { className: "text-danger ml-0.5", "aria-label": "obrigat\xF3rio" }, "*")),
|
|
77
|
+
/* @__PURE__ */ React.createElement("div", { className: ["flex", orientation === "horizontal" ? "flex-row gap-4 flex-wrap" : "flex-col gap-2"].join(" ") }, options.map((opt) => /* @__PURE__ */ React.createElement(
|
|
78
|
+
Radio,
|
|
79
|
+
{
|
|
80
|
+
key: opt.value,
|
|
81
|
+
name,
|
|
82
|
+
value: opt.value,
|
|
83
|
+
checked: value === opt.value,
|
|
84
|
+
onChange: () => onChange(opt.value),
|
|
85
|
+
label: opt.label,
|
|
86
|
+
description: opt.description,
|
|
87
|
+
disabled: opt.disabled,
|
|
88
|
+
size
|
|
89
|
+
}
|
|
90
|
+
))),
|
|
91
|
+
error && /* @__PURE__ */ React.createElement("p", { className: "text-caption text-danger-text" }, error)
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
Radio,
|
|
96
|
+
RadioGroup
|
|
97
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface RowActionItem {
|
|
5
|
+
label: string;
|
|
6
|
+
icon?: ReactNode;
|
|
7
|
+
variant?: 'default' | 'danger';
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
onClick: () => void;
|
|
10
|
+
}
|
|
11
|
+
interface RowActionsProps {
|
|
12
|
+
/** Rótulo do botão principal (ex: "Ver detalhes"). */
|
|
13
|
+
primaryLabel: string;
|
|
14
|
+
/** Se href, renderiza <a>; se onClick, renderiza <button>. */
|
|
15
|
+
primaryHref?: string;
|
|
16
|
+
primaryOnClick?: () => void;
|
|
17
|
+
/** Itens do menu de 3-pontinhos. Se vazio, o menu não é renderizado. */
|
|
18
|
+
items?: RowActionItem[];
|
|
19
|
+
/** Separador antes de itens "danger" (último bloco). default: true quando há danger items. */
|
|
20
|
+
dangerSeparator?: boolean;
|
|
21
|
+
}
|
|
22
|
+
declare function RowActions({ primaryLabel, primaryHref, primaryOnClick, items, dangerSeparator, }: RowActionsProps): react.JSX.Element;
|
|
23
|
+
|
|
24
|
+
export { type RowActionItem, RowActions, type RowActionsProps };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../chunk-ORMEWXMH.js";
|
|
3
|
+
import { MoreVertical } from "lucide-react";
|
|
4
|
+
import { Menu, MenuItem, MenuSeparator } from "./menu.js";
|
|
5
|
+
import { IconButton } from "./icon-button.js";
|
|
6
|
+
function RowActions({
|
|
7
|
+
primaryLabel,
|
|
8
|
+
primaryHref,
|
|
9
|
+
primaryOnClick,
|
|
10
|
+
items = [],
|
|
11
|
+
dangerSeparator
|
|
12
|
+
}) {
|
|
13
|
+
const hasDanger = items.some((i) => i.variant === "danger");
|
|
14
|
+
const showSep = dangerSeparator != null ? dangerSeparator : hasDanger;
|
|
15
|
+
const normalItems = showSep ? items.filter((i) => i.variant !== "danger") : items;
|
|
16
|
+
const dangerItems = showSep ? items.filter((i) => i.variant === "danger") : [];
|
|
17
|
+
const primaryCls = "inline-flex items-center gap-1 text-caption font-medium border border-stroke-default rounded-(--radius-control) px-2.5 py-1 text-fg-secondary hover:bg-surface-page hover:border-stroke-strong transition-colors whitespace-nowrap";
|
|
18
|
+
return /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-end gap-1" }, primaryHref ? /* @__PURE__ */ React.createElement("a", { href: primaryHref, className: primaryCls, onClick: (e) => e.stopPropagation() }, primaryLabel) : primaryOnClick ? /* @__PURE__ */ React.createElement(
|
|
19
|
+
"button",
|
|
20
|
+
{
|
|
21
|
+
type: "button",
|
|
22
|
+
className: primaryCls,
|
|
23
|
+
onClick: (e) => {
|
|
24
|
+
e.stopPropagation();
|
|
25
|
+
primaryOnClick();
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
primaryLabel
|
|
29
|
+
) : null, items.length > 0 && /* @__PURE__ */ React.createElement("div", { onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React.createElement(
|
|
30
|
+
Menu,
|
|
31
|
+
{
|
|
32
|
+
trigger: /* @__PURE__ */ React.createElement(
|
|
33
|
+
IconButton,
|
|
34
|
+
{
|
|
35
|
+
icon: /* @__PURE__ */ React.createElement(MoreVertical, null),
|
|
36
|
+
"aria-label": "Mais a\xE7\xF5es",
|
|
37
|
+
size: "sm",
|
|
38
|
+
variant: "ghost",
|
|
39
|
+
color: "secondary"
|
|
40
|
+
}
|
|
41
|
+
),
|
|
42
|
+
placement: "bottom-end",
|
|
43
|
+
minWidth: 160
|
|
44
|
+
},
|
|
45
|
+
({ close }) => /* @__PURE__ */ React.createElement(React.Fragment, null, normalItems.map((item, i) => /* @__PURE__ */ React.createElement(
|
|
46
|
+
MenuItem,
|
|
47
|
+
{
|
|
48
|
+
key: i,
|
|
49
|
+
icon: item.icon,
|
|
50
|
+
variant: item.variant,
|
|
51
|
+
disabled: item.disabled,
|
|
52
|
+
onClick: () => {
|
|
53
|
+
item.onClick();
|
|
54
|
+
close();
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
item.label
|
|
58
|
+
)), showSep && dangerItems.length > 0 && /* @__PURE__ */ React.createElement(MenuSeparator, null), dangerItems.map((item, i) => /* @__PURE__ */ React.createElement(
|
|
59
|
+
MenuItem,
|
|
60
|
+
{
|
|
61
|
+
key: `d-${i}`,
|
|
62
|
+
icon: item.icon,
|
|
63
|
+
variant: "danger",
|
|
64
|
+
disabled: item.disabled,
|
|
65
|
+
onClick: () => {
|
|
66
|
+
item.onClick();
|
|
67
|
+
close();
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
item.label
|
|
71
|
+
)))
|
|
72
|
+
)));
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
RowActions
|
|
76
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type SavingBarRegistration = {
|
|
5
|
+
/** Internal id assigned by usePageSavingBar — do not set manually. */
|
|
6
|
+
id?: string;
|
|
7
|
+
visible: boolean;
|
|
8
|
+
message?: string;
|
|
9
|
+
onSave?: () => void | Promise<void>;
|
|
10
|
+
onDiscard?: () => void;
|
|
11
|
+
pending?: boolean;
|
|
12
|
+
saveLabel?: string;
|
|
13
|
+
discardLabel?: string;
|
|
14
|
+
/** Optional third button shown between Discard and Save. Hidden when bars are aggregated. */
|
|
15
|
+
secondary?: {
|
|
16
|
+
label: string;
|
|
17
|
+
onClick: () => void;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
declare function SavingBarProvider({ children }: {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}): react.JSX.Element;
|
|
23
|
+
/**
|
|
24
|
+
* Register a saving bar for the current page/section.
|
|
25
|
+
* The DS renders a single floating bar that aggregates all registrations:
|
|
26
|
+
* - 0 visible → hidden
|
|
27
|
+
* - 1 visible → shown directly (message + Salvar + Descartar)
|
|
28
|
+
* - 2+ visible → "{N} alterações pendentes" + "Salvar tudo" + "Descartar tudo"
|
|
29
|
+
*
|
|
30
|
+
* Pass null to clear. Cleanup on unmount is automatic.
|
|
31
|
+
*/
|
|
32
|
+
declare function usePageSavingBar(reg: SavingBarRegistration | null, deps?: unknown[]): void;
|
|
33
|
+
/**
|
|
34
|
+
* #485 — true quando existe QUALQUER saving-bar visível. O FAB (mesmo canto inferior
|
|
35
|
+
* direito) usa isto pra se esconder e não ser tapado pela barra.
|
|
36
|
+
*/
|
|
37
|
+
declare function useSavingBarActive(): boolean;
|
|
38
|
+
declare function SavingBarRoot(): react.JSX.Element | null;
|
|
39
|
+
|
|
40
|
+
export { SavingBarProvider, type SavingBarRegistration, SavingBarRoot, usePageSavingBar, useSavingBarActive };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
__spreadProps,
|
|
4
|
+
__spreadValues
|
|
5
|
+
} from "../chunk-ORMEWXMH.js";
|
|
6
|
+
import {
|
|
7
|
+
createContext,
|
|
8
|
+
useCallback,
|
|
9
|
+
useContext,
|
|
10
|
+
useEffect,
|
|
11
|
+
useId,
|
|
12
|
+
useMemo,
|
|
13
|
+
useRef,
|
|
14
|
+
useState
|
|
15
|
+
} from "react";
|
|
16
|
+
import { Loader2 } from "lucide-react";
|
|
17
|
+
const SavingBarContext = createContext({
|
|
18
|
+
bars: /* @__PURE__ */ new Map(),
|
|
19
|
+
register: () => {
|
|
20
|
+
},
|
|
21
|
+
unregister: () => {
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
function SavingBarProvider({ children }) {
|
|
25
|
+
const [bars, setBars] = useState(() => /* @__PURE__ */ new Map());
|
|
26
|
+
const register = useCallback((id, reg) => {
|
|
27
|
+
setBars((prev) => {
|
|
28
|
+
const next = new Map(prev);
|
|
29
|
+
next.set(id, __spreadProps(__spreadValues({}, reg), { id }));
|
|
30
|
+
return next;
|
|
31
|
+
});
|
|
32
|
+
}, []);
|
|
33
|
+
const unregister = useCallback((id) => {
|
|
34
|
+
setBars((prev) => {
|
|
35
|
+
if (!prev.has(id)) return prev;
|
|
36
|
+
const next = new Map(prev);
|
|
37
|
+
next.delete(id);
|
|
38
|
+
return next;
|
|
39
|
+
});
|
|
40
|
+
}, []);
|
|
41
|
+
const value = useMemo(() => ({ bars, register, unregister }), [bars, register, unregister]);
|
|
42
|
+
return /* @__PURE__ */ React.createElement(SavingBarContext.Provider, { value }, children);
|
|
43
|
+
}
|
|
44
|
+
function usePageSavingBar(reg, deps = []) {
|
|
45
|
+
const id = useId();
|
|
46
|
+
const { register, unregister } = useContext(SavingBarContext);
|
|
47
|
+
const regRef = useRef(reg);
|
|
48
|
+
regRef.current = reg;
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (regRef.current) register(id, regRef.current);
|
|
51
|
+
else unregister(id);
|
|
52
|
+
return () => unregister(id);
|
|
53
|
+
}, [id, register, unregister, ...deps]);
|
|
54
|
+
}
|
|
55
|
+
function useSavingBarActive() {
|
|
56
|
+
const { bars } = useContext(SavingBarContext);
|
|
57
|
+
for (const b of bars.values()) if (b.visible) return true;
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
function SavingBarRoot() {
|
|
61
|
+
var _a, _b, _c;
|
|
62
|
+
const { bars } = useContext(SavingBarContext);
|
|
63
|
+
const [aggPending, setAggPending] = useState(false);
|
|
64
|
+
const visible = useMemo(
|
|
65
|
+
() => [...bars.values()].filter((b) => b.visible),
|
|
66
|
+
[bars]
|
|
67
|
+
);
|
|
68
|
+
if (visible.length === 0) return null;
|
|
69
|
+
const single = visible.length === 1 ? visible[0] : null;
|
|
70
|
+
const anyPending = aggPending || visible.some((b) => b.pending);
|
|
71
|
+
async function saveAll() {
|
|
72
|
+
setAggPending(true);
|
|
73
|
+
try {
|
|
74
|
+
for (const b of visible) {
|
|
75
|
+
if (b.onSave) await b.onSave();
|
|
76
|
+
}
|
|
77
|
+
} finally {
|
|
78
|
+
setAggPending(false);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function discardAll() {
|
|
82
|
+
var _a2;
|
|
83
|
+
for (const b of visible) (_a2 = b.onDiscard) == null ? void 0 : _a2.call(b);
|
|
84
|
+
}
|
|
85
|
+
const message = (_a = single == null ? void 0 : single.message) != null ? _a : null;
|
|
86
|
+
const saveLabel = (_b = single == null ? void 0 : single.saveLabel) != null ? _b : "Salvar tudo";
|
|
87
|
+
const discardLabel = (_c = single == null ? void 0 : single.discardLabel) != null ? _c : "Descartar tudo";
|
|
88
|
+
const onSave = single ? single.onSave : saveAll;
|
|
89
|
+
const onDiscard = single ? single.onDiscard : discardAll;
|
|
90
|
+
const secondary = single == null ? void 0 : single.secondary;
|
|
91
|
+
return /* @__PURE__ */ React.createElement("div", { className: "fixed bottom-3 right-6 z-50 transition-all duration-300 ease-out" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-3 rounded-(--radius-card) px-4 py-3 [background:var(--saving-bar-bg)] [box-shadow:var(--saving-bar-shadow)]" }, message && /* @__PURE__ */ React.createElement("span", { className: "text-label pr-1 [color:var(--saving-bar-message)]" }, message), onDiscard && /* @__PURE__ */ React.createElement(
|
|
92
|
+
"button",
|
|
93
|
+
{
|
|
94
|
+
type: "button",
|
|
95
|
+
onClick: onDiscard,
|
|
96
|
+
disabled: anyPending,
|
|
97
|
+
className: "rounded-(--radius-card) border px-3 py-1.5 text-label font-medium transition-colors disabled:opacity-40 [border-color:var(--saving-bar-discard-border)] [color:var(--saving-bar-discard-text)] hover:[border-color:var(--saving-bar-discard-border-hover)] hover:[color:var(--saving-bar-discard-text-hover)]"
|
|
98
|
+
},
|
|
99
|
+
discardLabel
|
|
100
|
+
), secondary && /* @__PURE__ */ React.createElement(
|
|
101
|
+
"button",
|
|
102
|
+
{
|
|
103
|
+
type: "button",
|
|
104
|
+
onClick: secondary.onClick,
|
|
105
|
+
disabled: anyPending,
|
|
106
|
+
className: "rounded-(--radius-card) border px-3 py-1.5 text-label font-medium transition-colors disabled:opacity-40 [border-color:var(--saving-bar-discard-border)] [color:var(--saving-bar-discard-text)] hover:[border-color:var(--saving-bar-discard-border-hover)] hover:[color:var(--saving-bar-discard-text-hover)]"
|
|
107
|
+
},
|
|
108
|
+
secondary.label
|
|
109
|
+
), onSave && /* @__PURE__ */ React.createElement(
|
|
110
|
+
"button",
|
|
111
|
+
{
|
|
112
|
+
type: "button",
|
|
113
|
+
onClick: () => onSave(),
|
|
114
|
+
disabled: anyPending,
|
|
115
|
+
className: "rounded-(--radius-card) px-4 py-1.5 text-label font-medium transition-colors disabled:opacity-50 flex items-center gap-2 min-w-[80px] justify-center [background:var(--saving-bar-save-bg)] [color:var(--saving-bar-save-text)] hover:[background:var(--saving-bar-save-bg-hover)]"
|
|
116
|
+
},
|
|
117
|
+
anyPending ? /* @__PURE__ */ React.createElement(Loader2, { className: "w-4 h-4 animate-spin" }) : saveLabel
|
|
118
|
+
)));
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
SavingBarProvider,
|
|
122
|
+
SavingBarRoot,
|
|
123
|
+
usePageSavingBar,
|
|
124
|
+
useSavingBarActive
|
|
125
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface SavingBarProps {
|
|
5
|
+
visible: boolean;
|
|
6
|
+
onSave?: () => void;
|
|
7
|
+
onDiscard?: () => void;
|
|
8
|
+
pending?: boolean;
|
|
9
|
+
saveLabel?: string;
|
|
10
|
+
discardLabel?: string;
|
|
11
|
+
message?: string;
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
/** floating = fixed bottom-right; inline = inside page flow */
|
|
14
|
+
variant?: 'floating' | 'inline';
|
|
15
|
+
}
|
|
16
|
+
declare function SavingBar({ visible, onSave, onDiscard, pending, saveLabel, discardLabel, message, children, variant, }: SavingBarProps): react.JSX.Element;
|
|
17
|
+
|
|
18
|
+
export { SavingBar, type SavingBarProps };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../chunk-ORMEWXMH.js";
|
|
3
|
+
import { Loader2 } from "lucide-react";
|
|
4
|
+
function SavingBar({
|
|
5
|
+
visible,
|
|
6
|
+
onSave,
|
|
7
|
+
onDiscard,
|
|
8
|
+
pending = false,
|
|
9
|
+
saveLabel = "Salvar",
|
|
10
|
+
discardLabel = "Descartar",
|
|
11
|
+
message,
|
|
12
|
+
children,
|
|
13
|
+
variant = "floating"
|
|
14
|
+
}) {
|
|
15
|
+
const pill = /* @__PURE__ */ React.createElement(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
className: [
|
|
19
|
+
"flex items-center gap-3 rounded-(--radius-card) px-4 py-3",
|
|
20
|
+
"[background:var(--saving-bar-bg)]",
|
|
21
|
+
variant === "floating" ? "[box-shadow:var(--saving-bar-shadow)]" : ""
|
|
22
|
+
].filter(Boolean).join(" ")
|
|
23
|
+
},
|
|
24
|
+
message && /* @__PURE__ */ React.createElement("span", { className: "text-label pr-1 [color:var(--saving-bar-message)]" }, message),
|
|
25
|
+
children,
|
|
26
|
+
onDiscard && /* @__PURE__ */ React.createElement(
|
|
27
|
+
"button",
|
|
28
|
+
{
|
|
29
|
+
type: "button",
|
|
30
|
+
onClick: onDiscard,
|
|
31
|
+
disabled: pending,
|
|
32
|
+
className: "rounded-(--radius-card) border px-3 py-1.5 text-label font-medium transition-colors disabled:opacity-40 [border-color:var(--saving-bar-discard-border)] [color:var(--saving-bar-discard-text)] hover:[border-color:var(--saving-bar-discard-border-hover)] hover:[color:var(--saving-bar-discard-text-hover)]"
|
|
33
|
+
},
|
|
34
|
+
discardLabel
|
|
35
|
+
),
|
|
36
|
+
onSave && /* @__PURE__ */ React.createElement(
|
|
37
|
+
"button",
|
|
38
|
+
{
|
|
39
|
+
type: "button",
|
|
40
|
+
onClick: onSave,
|
|
41
|
+
disabled: pending,
|
|
42
|
+
className: "rounded-(--radius-card) px-4 py-1.5 text-label font-medium transition-colors disabled:opacity-50 flex items-center gap-2 min-w-[80px] justify-center [background:var(--saving-bar-save-bg)] [color:var(--saving-bar-save-text)] hover:[background:var(--saving-bar-save-bg-hover)]"
|
|
43
|
+
},
|
|
44
|
+
pending ? /* @__PURE__ */ React.createElement(Loader2, { className: "w-4 h-4 animate-spin" }) : saveLabel
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
if (variant === "inline") {
|
|
48
|
+
return /* @__PURE__ */ React.createElement(
|
|
49
|
+
"div",
|
|
50
|
+
{
|
|
51
|
+
className: [
|
|
52
|
+
"flex justify-end mt-8 transition-all duration-300 ease-out",
|
|
53
|
+
visible ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
|
|
54
|
+
].join(" ")
|
|
55
|
+
},
|
|
56
|
+
pill
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return /* @__PURE__ */ React.createElement(
|
|
60
|
+
"div",
|
|
61
|
+
{
|
|
62
|
+
className: [
|
|
63
|
+
"fixed bottom-3 right-6 z-50 transition-all duration-300 ease-out",
|
|
64
|
+
visible ? "translate-y-0 opacity-100 pointer-events-auto" : "translate-y-4 opacity-0 pointer-events-none"
|
|
65
|
+
].join(" ")
|
|
66
|
+
},
|
|
67
|
+
pill
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
SavingBar
|
|
72
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { InputHTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Search — input dedicado de busca. Ícone leading + botão clear quando tem valor.
|
|
6
|
+
*
|
|
7
|
+
* Uso (uncontrolled):
|
|
8
|
+
* <Search placeholder="Buscar pedidos..." onSearch={q => doSearch(q)} />
|
|
9
|
+
*
|
|
10
|
+
* Uso (controlled):
|
|
11
|
+
* <Search value={q} onChange={e => setQ(e.target.value)} onClear={() => setQ('')} />
|
|
12
|
+
*
|
|
13
|
+
* Disparos de busca:
|
|
14
|
+
* - onSearch(query): debounce automático (default 250ms) ou Enter pressed
|
|
15
|
+
* - onChange: cada keystroke (caso queira live-search direto)
|
|
16
|
+
*/
|
|
17
|
+
interface SearchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'onChange' | 'size'> {
|
|
18
|
+
onChange?: InputHTMLAttributes<HTMLInputElement>['onChange'];
|
|
19
|
+
/** Callback debounced (250ms) ou em Enter. */
|
|
20
|
+
onSearch?: (query: string) => void;
|
|
21
|
+
/** Callback do botão clear. */
|
|
22
|
+
onClear?: () => void;
|
|
23
|
+
/** Tamanho. default = md. */
|
|
24
|
+
size?: 'sm' | 'md' | 'lg';
|
|
25
|
+
/** Largura full ou hug. default = full. */
|
|
26
|
+
width?: 'full' | 'hug';
|
|
27
|
+
}
|
|
28
|
+
declare const Search: react.ForwardRefExoticComponent<SearchProps & react.RefAttributes<HTMLInputElement>>;
|
|
29
|
+
|
|
30
|
+
export { Search, type SearchProps };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
__objRest,
|
|
4
|
+
__spreadValues
|
|
5
|
+
} from "../chunk-ORMEWXMH.js";
|
|
6
|
+
import { forwardRef, useEffect, useRef } from "react";
|
|
7
|
+
import { Search as SearchIcon, X } from "lucide-react";
|
|
8
|
+
const SIZE_CLASS = {
|
|
9
|
+
sm: "h-control-sm text-caption pl-8 pr-7",
|
|
10
|
+
md: "h-control-md text-label pl-9 pr-8",
|
|
11
|
+
lg: "h-control-lg text-body pl-10 pr-9"
|
|
12
|
+
};
|
|
13
|
+
const ICON_SIZE = { sm: 14, md: 16, lg: 18 };
|
|
14
|
+
const ICON_POS = { sm: "left-2.5", md: "left-3", lg: "left-3.5" };
|
|
15
|
+
const CLEAR_POS = { sm: "right-1.5", md: "right-2", lg: "right-2.5" };
|
|
16
|
+
const Search = forwardRef(function Search2(_a, ref) {
|
|
17
|
+
var _b = _a, { size = "md", width = "full", onSearch, onClear, onChange, value, className = "" } = _b, rest = __objRest(_b, ["size", "width", "onSearch", "onClear", "onChange", "value", "className"]);
|
|
18
|
+
const hasValue = !!(value != null ? value : "");
|
|
19
|
+
const debounceRef = useRef(null);
|
|
20
|
+
useEffect(() => () => {
|
|
21
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
22
|
+
}, []);
|
|
23
|
+
function handleChange(e) {
|
|
24
|
+
onChange == null ? void 0 : onChange(e);
|
|
25
|
+
if (onSearch) {
|
|
26
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
27
|
+
debounceRef.current = setTimeout(() => onSearch(e.target.value), 250);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function handleClear() {
|
|
31
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
32
|
+
onClear == null ? void 0 : onClear();
|
|
33
|
+
}
|
|
34
|
+
return /* @__PURE__ */ React.createElement("div", { className: ["relative inline-flex", width === "full" ? "w-full" : "w-auto"].join(" ") }, /* @__PURE__ */ React.createElement(
|
|
35
|
+
SearchIcon,
|
|
36
|
+
{
|
|
37
|
+
size: ICON_SIZE[size],
|
|
38
|
+
className: ["absolute top-1/2 -translate-y-1/2 text-fg-muted pointer-events-none", ICON_POS[size]].join(" ")
|
|
39
|
+
}
|
|
40
|
+
), /* @__PURE__ */ React.createElement(
|
|
41
|
+
"input",
|
|
42
|
+
__spreadValues({
|
|
43
|
+
ref,
|
|
44
|
+
type: "search",
|
|
45
|
+
role: "searchbox",
|
|
46
|
+
value,
|
|
47
|
+
onChange: handleChange,
|
|
48
|
+
onKeyDown: (e) => {
|
|
49
|
+
if (e.key === "Enter") {
|
|
50
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
51
|
+
onSearch == null ? void 0 : onSearch(e.target.value);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
className: [
|
|
55
|
+
"w-full rounded-(--radius-control) bg-surface-default text-fg-primary placeholder:text-fg-placeholder",
|
|
56
|
+
"border border-stroke-control transition-colors outline-none",
|
|
57
|
+
"focus:border-stroke-focus focus:ring-2 focus:ring-stroke-focus/20",
|
|
58
|
+
"[&::-webkit-search-cancel-button]:hidden",
|
|
59
|
+
SIZE_CLASS[size],
|
|
60
|
+
className
|
|
61
|
+
].join(" ")
|
|
62
|
+
}, rest)
|
|
63
|
+
), hasValue && /* @__PURE__ */ React.createElement(
|
|
64
|
+
"button",
|
|
65
|
+
{
|
|
66
|
+
type: "button",
|
|
67
|
+
onClick: handleClear,
|
|
68
|
+
"aria-label": "Limpar busca",
|
|
69
|
+
className: [
|
|
70
|
+
"absolute top-1/2 -translate-y-1/2 inline-flex items-center justify-center",
|
|
71
|
+
"rounded-(--radius-control) text-fg-muted hover:text-fg-primary transition-colors",
|
|
72
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-stroke-focus",
|
|
73
|
+
CLEAR_POS[size]
|
|
74
|
+
].join(" ")
|
|
75
|
+
},
|
|
76
|
+
/* @__PURE__ */ React.createElement(X, { size: ICON_SIZE[size] - 2 })
|
|
77
|
+
));
|
|
78
|
+
});
|
|
79
|
+
export {
|
|
80
|
+
Search
|
|
81
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface SectionCardProps {
|
|
5
|
+
label: string;
|
|
6
|
+
/** Secondary text shown beside the label (e.g. a subtitle or count) */
|
|
7
|
+
badge?: string;
|
|
8
|
+
open: boolean;
|
|
9
|
+
onToggle: () => void;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
declare function SectionCard({ label, badge, open, onToggle, children }: SectionCardProps): react.JSX.Element;
|
|
13
|
+
|
|
14
|
+
export { SectionCard, type SectionCardProps };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import "../chunk-ORMEWXMH.js";
|
|
3
|
+
import { ChevronDown, ChevronRight } from "lucide-react";
|
|
4
|
+
function SectionCard({ label, badge, open, onToggle, children }) {
|
|
5
|
+
return /* @__PURE__ */ React.createElement(
|
|
6
|
+
"div",
|
|
7
|
+
{
|
|
8
|
+
className: [
|
|
9
|
+
"rounded-(--radius-card) overflow-hidden transition-colors border",
|
|
10
|
+
open ? "[border-color:var(--section-card-border-active)]" : "[border-color:var(--section-card-border)]"
|
|
11
|
+
].join(" ")
|
|
12
|
+
},
|
|
13
|
+
/* @__PURE__ */ React.createElement(
|
|
14
|
+
"button",
|
|
15
|
+
{
|
|
16
|
+
type: "button",
|
|
17
|
+
onClick: onToggle,
|
|
18
|
+
className: [
|
|
19
|
+
"w-full flex items-center justify-between px-4 py-3 text-left transition-colors",
|
|
20
|
+
open ? "[background:var(--section-card-header-bg-active)]" : "hover:[background:var(--section-card-header-bg-hover)]"
|
|
21
|
+
].join(" ")
|
|
22
|
+
},
|
|
23
|
+
/* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ React.createElement(
|
|
24
|
+
"span",
|
|
25
|
+
{
|
|
26
|
+
className: [
|
|
27
|
+
"text-caption font-semibold uppercase tracking-wide shrink-0",
|
|
28
|
+
open ? "[color:var(--section-card-label-active)]" : "[color:var(--section-card-label)]"
|
|
29
|
+
].join(" ")
|
|
30
|
+
},
|
|
31
|
+
label
|
|
32
|
+
), badge && /* @__PURE__ */ React.createElement(
|
|
33
|
+
"span",
|
|
34
|
+
{
|
|
35
|
+
className: [
|
|
36
|
+
"text-caption truncate min-w-0",
|
|
37
|
+
open ? "[color:var(--section-card-badge-active)]" : "[color:var(--section-card-badge)]"
|
|
38
|
+
].join(" ")
|
|
39
|
+
},
|
|
40
|
+
badge
|
|
41
|
+
)),
|
|
42
|
+
open ? /* @__PURE__ */ React.createElement(ChevronDown, { className: "w-4 h-4 shrink-0 [color:var(--section-card-chevron)]" }) : /* @__PURE__ */ React.createElement(ChevronRight, { className: "w-4 h-4 shrink-0 [color:var(--section-card-chevron)]" })
|
|
43
|
+
),
|
|
44
|
+
open && /* @__PURE__ */ React.createElement("div", { className: "px-4 pb-4 pt-4 space-y-4 [border-top:1px_solid_var(--section-card-divider)] [background:var(--surface-default)]" }, children)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
SectionCard
|
|
49
|
+
};
|