@moeve-ui/ui 0.1.3 → 0.2.1

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/dist/index.d.mts CHANGED
@@ -85,6 +85,8 @@ declare function TrendDownIcon(props: IconProps): react.JSX.Element;
85
85
  declare function FuelIcon(props: IconProps): react.JSX.Element;
86
86
  declare function WalletIcon(props: IconProps): react.JSX.Element;
87
87
  declare function CheckCircleIcon(props: IconProps): react.JSX.Element;
88
+ declare function CalendarIcon(props: IconProps): react.JSX.Element;
89
+ declare function UploadIcon(props: IconProps): react.JSX.Element;
88
90
  declare function XIcon(props: IconProps): react.JSX.Element;
89
91
  /**
90
92
  * Solid/filled icon set, exported directly from the "Redinamic-tec" Figma
@@ -320,6 +322,64 @@ interface MiniMapCardProps {
320
322
  */
321
323
  declare function MiniMapCard({ overlayTitle, overlayLinkLabel, competitorCount }: MiniMapCardProps): react.JSX.Element;
322
324
 
325
+ interface WeekdayPickerProps {
326
+ /** Exactly 7 short labels, in whatever order/language the caller uses (e.g. ["Lun", ..., "Dom"]). The index is the day value passed to onToggle/selected. */
327
+ labels: readonly string[];
328
+ /** Day indices currently toggled on. */
329
+ selected: readonly number[];
330
+ onToggle: (day: number) => void;
331
+ className?: string;
332
+ }
333
+ /**
334
+ * Circular day-of-week toggle row - previously hand-duplicated (with
335
+ * slightly different styles) in redisplay-web's QuoteWizard and
336
+ * RecurringPlansClient. Generic on purpose: the caller owns the labels
337
+ * (language/order) and which days start selected.
338
+ */
339
+ declare function WeekdayPicker({ labels, selected, onToggle, className }: WeekdayPickerProps): react.JSX.Element;
340
+
341
+ interface SelectableCardProps {
342
+ icon?: ReactNode;
343
+ title: string;
344
+ subtitle?: string;
345
+ /**
346
+ * Optional visual header (a map, an illustration, anything) rendered in a
347
+ * fixed-height rounded-top slot above the title - switches the card from
348
+ * the default horizontal "icon + text" row into a vertical "listing card"
349
+ * layout (media on top, text below), the same shape a photo-card grid
350
+ * needs. The caller owns what goes in it - this component has no opinion
351
+ * on images vs. maps vs. anything else.
352
+ */
353
+ media?: ReactNode;
354
+ selected?: boolean;
355
+ onClick: () => void;
356
+ className?: string;
357
+ }
358
+ /**
359
+ * Generic clickable "pick one of these" card: an icon chip, a title, an
360
+ * optional subtitle, and a selected state. Not tied to any domain (not
361
+ * "StationCard") - meant for any picker across the 3 apps (redisplay-web's
362
+ * station picker today, any future list-of-options screen tomorrow).
363
+ */
364
+ declare function SelectableCard({ icon, title, subtitle, media, selected, onClick, className }: SelectableCardProps): react.JSX.Element;
365
+
366
+ interface FileDropzoneProps {
367
+ accept?: string;
368
+ onFileSelected: (file: File | null) => void;
369
+ /** Name of the currently-selected file, if any - the caller owns the File itself, this component is stateless about it. */
370
+ selectedFileName?: string | null;
371
+ label?: string;
372
+ hint?: string;
373
+ className?: string;
374
+ }
375
+ /**
376
+ * Restyled file picker: a dashed dropzone (click or drag-and-drop) instead
377
+ * of a bare `<input type="file">`. The native input still does the actual
378
+ * work (hidden, triggered via the visible box) - this only changes how it
379
+ * looks, not the underlying file-selection contract.
380
+ */
381
+ declare function FileDropzone({ accept, onFileSelected, selectedFileName, label, hint, className, }: FileDropzoneProps): react.JSX.Element;
382
+
323
383
  interface SidebarStation {
324
384
  id: string;
325
385
  label: string;
@@ -392,4 +452,4 @@ interface ConfirmDialogProps {
392
452
  */
393
453
  declare function ConfirmDialog({ open, onClose, onConfirm, title, productLabel, description, currentPrice, newPrice, marginImpactLabel, volumeImpactLabel, confirming, }: ConfirmDialogProps): react.JSX.Element | null;
394
454
 
395
- export { ArrowDownIcon, ArrowUpIcon, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeTone, BoltIcon, Button, type ButtonProps, type ButtonVariant, Card, type CardProps, CheckCircleIcon, ChevronDownIcon, type ColorTokens, CompetitorRow, type CompetitorRowProps, type CompetitorTrend, ConfirmDialog, type ConfirmDialogProps, DecisionFactorRow, type DecisionFactorRowProps, FuelIcon, FuelPumpSolidIcon, LogOutIcon, MapPinIcon, MiniMapCard, type MiniMapCardProps, NavItem, type NavItemProps, PriceRangeSlider, type PriceRangeSliderProps, ProgressBar, type ProgressBarProps, RefreshIcon, type SegmentedTabOption, SegmentedTabs, type SegmentedTabsProps, Sidebar, type SidebarNavItem, type SidebarProps, type SidebarStation, type SidebarUser, Snackbar, type SnackbarProps, type SnackbarTone, StatTile, type StatTileProps, TagIcon, TargetIcon, TopBar, type TopBarProps, TrendDownIcon, TrendUpIcon, TrendUpSolidIcon, UserCircleIcon, WalletIcon, WalletSolidIcon, XIcon, colors };
455
+ export { ArrowDownIcon, ArrowUpIcon, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeTone, BoltIcon, Button, type ButtonProps, type ButtonVariant, CalendarIcon, Card, type CardProps, CheckCircleIcon, ChevronDownIcon, type ColorTokens, CompetitorRow, type CompetitorRowProps, type CompetitorTrend, ConfirmDialog, type ConfirmDialogProps, DecisionFactorRow, type DecisionFactorRowProps, FileDropzone, type FileDropzoneProps, FuelIcon, FuelPumpSolidIcon, LogOutIcon, MapPinIcon, MiniMapCard, type MiniMapCardProps, NavItem, type NavItemProps, PriceRangeSlider, type PriceRangeSliderProps, ProgressBar, type ProgressBarProps, RefreshIcon, type SegmentedTabOption, SegmentedTabs, type SegmentedTabsProps, SelectableCard, type SelectableCardProps, Sidebar, type SidebarNavItem, type SidebarProps, type SidebarStation, type SidebarUser, Snackbar, type SnackbarProps, type SnackbarTone, StatTile, type StatTileProps, TagIcon, TargetIcon, TopBar, type TopBarProps, TrendDownIcon, TrendUpIcon, TrendUpSolidIcon, UploadIcon, UserCircleIcon, WalletIcon, WalletSolidIcon, WeekdayPicker, type WeekdayPickerProps, XIcon, colors };
package/dist/index.d.ts CHANGED
@@ -85,6 +85,8 @@ declare function TrendDownIcon(props: IconProps): react.JSX.Element;
85
85
  declare function FuelIcon(props: IconProps): react.JSX.Element;
86
86
  declare function WalletIcon(props: IconProps): react.JSX.Element;
87
87
  declare function CheckCircleIcon(props: IconProps): react.JSX.Element;
88
+ declare function CalendarIcon(props: IconProps): react.JSX.Element;
89
+ declare function UploadIcon(props: IconProps): react.JSX.Element;
88
90
  declare function XIcon(props: IconProps): react.JSX.Element;
89
91
  /**
90
92
  * Solid/filled icon set, exported directly from the "Redinamic-tec" Figma
@@ -320,6 +322,64 @@ interface MiniMapCardProps {
320
322
  */
321
323
  declare function MiniMapCard({ overlayTitle, overlayLinkLabel, competitorCount }: MiniMapCardProps): react.JSX.Element;
322
324
 
325
+ interface WeekdayPickerProps {
326
+ /** Exactly 7 short labels, in whatever order/language the caller uses (e.g. ["Lun", ..., "Dom"]). The index is the day value passed to onToggle/selected. */
327
+ labels: readonly string[];
328
+ /** Day indices currently toggled on. */
329
+ selected: readonly number[];
330
+ onToggle: (day: number) => void;
331
+ className?: string;
332
+ }
333
+ /**
334
+ * Circular day-of-week toggle row - previously hand-duplicated (with
335
+ * slightly different styles) in redisplay-web's QuoteWizard and
336
+ * RecurringPlansClient. Generic on purpose: the caller owns the labels
337
+ * (language/order) and which days start selected.
338
+ */
339
+ declare function WeekdayPicker({ labels, selected, onToggle, className }: WeekdayPickerProps): react.JSX.Element;
340
+
341
+ interface SelectableCardProps {
342
+ icon?: ReactNode;
343
+ title: string;
344
+ subtitle?: string;
345
+ /**
346
+ * Optional visual header (a map, an illustration, anything) rendered in a
347
+ * fixed-height rounded-top slot above the title - switches the card from
348
+ * the default horizontal "icon + text" row into a vertical "listing card"
349
+ * layout (media on top, text below), the same shape a photo-card grid
350
+ * needs. The caller owns what goes in it - this component has no opinion
351
+ * on images vs. maps vs. anything else.
352
+ */
353
+ media?: ReactNode;
354
+ selected?: boolean;
355
+ onClick: () => void;
356
+ className?: string;
357
+ }
358
+ /**
359
+ * Generic clickable "pick one of these" card: an icon chip, a title, an
360
+ * optional subtitle, and a selected state. Not tied to any domain (not
361
+ * "StationCard") - meant for any picker across the 3 apps (redisplay-web's
362
+ * station picker today, any future list-of-options screen tomorrow).
363
+ */
364
+ declare function SelectableCard({ icon, title, subtitle, media, selected, onClick, className }: SelectableCardProps): react.JSX.Element;
365
+
366
+ interface FileDropzoneProps {
367
+ accept?: string;
368
+ onFileSelected: (file: File | null) => void;
369
+ /** Name of the currently-selected file, if any - the caller owns the File itself, this component is stateless about it. */
370
+ selectedFileName?: string | null;
371
+ label?: string;
372
+ hint?: string;
373
+ className?: string;
374
+ }
375
+ /**
376
+ * Restyled file picker: a dashed dropzone (click or drag-and-drop) instead
377
+ * of a bare `<input type="file">`. The native input still does the actual
378
+ * work (hidden, triggered via the visible box) - this only changes how it
379
+ * looks, not the underlying file-selection contract.
380
+ */
381
+ declare function FileDropzone({ accept, onFileSelected, selectedFileName, label, hint, className, }: FileDropzoneProps): react.JSX.Element;
382
+
323
383
  interface SidebarStation {
324
384
  id: string;
325
385
  label: string;
@@ -392,4 +452,4 @@ interface ConfirmDialogProps {
392
452
  */
393
453
  declare function ConfirmDialog({ open, onClose, onConfirm, title, productLabel, description, currentPrice, newPrice, marginImpactLabel, volumeImpactLabel, confirming, }: ConfirmDialogProps): react.JSX.Element | null;
394
454
 
395
- export { ArrowDownIcon, ArrowUpIcon, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeTone, BoltIcon, Button, type ButtonProps, type ButtonVariant, Card, type CardProps, CheckCircleIcon, ChevronDownIcon, type ColorTokens, CompetitorRow, type CompetitorRowProps, type CompetitorTrend, ConfirmDialog, type ConfirmDialogProps, DecisionFactorRow, type DecisionFactorRowProps, FuelIcon, FuelPumpSolidIcon, LogOutIcon, MapPinIcon, MiniMapCard, type MiniMapCardProps, NavItem, type NavItemProps, PriceRangeSlider, type PriceRangeSliderProps, ProgressBar, type ProgressBarProps, RefreshIcon, type SegmentedTabOption, SegmentedTabs, type SegmentedTabsProps, Sidebar, type SidebarNavItem, type SidebarProps, type SidebarStation, type SidebarUser, Snackbar, type SnackbarProps, type SnackbarTone, StatTile, type StatTileProps, TagIcon, TargetIcon, TopBar, type TopBarProps, TrendDownIcon, TrendUpIcon, TrendUpSolidIcon, UserCircleIcon, WalletIcon, WalletSolidIcon, XIcon, colors };
455
+ export { ArrowDownIcon, ArrowUpIcon, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeTone, BoltIcon, Button, type ButtonProps, type ButtonVariant, CalendarIcon, Card, type CardProps, CheckCircleIcon, ChevronDownIcon, type ColorTokens, CompetitorRow, type CompetitorRowProps, type CompetitorTrend, ConfirmDialog, type ConfirmDialogProps, DecisionFactorRow, type DecisionFactorRowProps, FileDropzone, type FileDropzoneProps, FuelIcon, FuelPumpSolidIcon, LogOutIcon, MapPinIcon, MiniMapCard, type MiniMapCardProps, NavItem, type NavItemProps, PriceRangeSlider, type PriceRangeSliderProps, ProgressBar, type ProgressBarProps, RefreshIcon, type SegmentedTabOption, SegmentedTabs, type SegmentedTabsProps, SelectableCard, type SelectableCardProps, Sidebar, type SidebarNavItem, type SidebarProps, type SidebarStation, type SidebarUser, Snackbar, type SnackbarProps, type SnackbarTone, StatTile, type StatTileProps, TagIcon, TargetIcon, TopBar, type TopBarProps, TrendDownIcon, TrendUpIcon, TrendUpSolidIcon, UploadIcon, UserCircleIcon, WalletIcon, WalletSolidIcon, WeekdayPicker, type WeekdayPickerProps, XIcon, colors };
package/dist/index.js CHANGED
@@ -26,12 +26,14 @@ __export(src_exports, {
26
26
  Badge: () => Badge,
27
27
  BoltIcon: () => BoltIcon,
28
28
  Button: () => Button,
29
+ CalendarIcon: () => CalendarIcon,
29
30
  Card: () => Card,
30
31
  CheckCircleIcon: () => CheckCircleIcon,
31
32
  ChevronDownIcon: () => ChevronDownIcon,
32
33
  CompetitorRow: () => CompetitorRow,
33
34
  ConfirmDialog: () => ConfirmDialog,
34
35
  DecisionFactorRow: () => DecisionFactorRow,
36
+ FileDropzone: () => FileDropzone,
35
37
  FuelIcon: () => FuelIcon,
36
38
  FuelPumpSolidIcon: () => FuelPumpSolidIcon,
37
39
  LogOutIcon: () => LogOutIcon,
@@ -42,6 +44,7 @@ __export(src_exports, {
42
44
  ProgressBar: () => ProgressBar,
43
45
  RefreshIcon: () => RefreshIcon,
44
46
  SegmentedTabs: () => SegmentedTabs,
47
+ SelectableCard: () => SelectableCard,
45
48
  Sidebar: () => Sidebar,
46
49
  Snackbar: () => Snackbar,
47
50
  StatTile: () => StatTile,
@@ -51,9 +54,11 @@ __export(src_exports, {
51
54
  TrendDownIcon: () => TrendDownIcon,
52
55
  TrendUpIcon: () => TrendUpIcon,
53
56
  TrendUpSolidIcon: () => TrendUpSolidIcon,
57
+ UploadIcon: () => UploadIcon,
54
58
  UserCircleIcon: () => UserCircleIcon,
55
59
  WalletIcon: () => WalletIcon,
56
60
  WalletSolidIcon: () => WalletSolidIcon,
61
+ WeekdayPicker: () => WeekdayPicker,
57
62
  XIcon: () => XIcon,
58
63
  colors: () => colors
59
64
  });
@@ -200,6 +205,21 @@ function CheckCircleIcon(props) {
200
205
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m8.5 12.5 2.5 2.5 5-5" })
201
206
  ] });
202
207
  }
208
+ function CalendarIcon(props) {
209
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...base, stroke: "currentColor", ...props, children: [
210
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "5", width: "18", height: "16", rx: "2" }),
211
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "3", y1: "10", x2: "21", y2: "10" }),
212
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "3", x2: "8", y2: "7" }),
213
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "16", y1: "3", x2: "16", y2: "7" })
214
+ ] });
215
+ }
216
+ function UploadIcon(props) {
217
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...base, stroke: "currentColor", ...props, children: [
218
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 16V4" }),
219
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m7 9 5-5 5 5" }),
220
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 16v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3" })
221
+ ] });
222
+ }
203
223
  function XIcon(props) {
204
224
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...base, stroke: "currentColor", ...props, children: [
205
225
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18 6 6 18" }),
@@ -584,8 +604,126 @@ function MiniMapCard({ overlayTitle, overlayLinkLabel, competitorCount }) {
584
604
  ] });
585
605
  }
586
606
 
587
- // src/organisms/Sidebar/Sidebar.tsx
607
+ // src/molecules/WeekdayPicker/WeekdayPicker.tsx
588
608
  var import_jsx_runtime15 = require("react/jsx-runtime");
609
+ function WeekdayPicker({ labels, selected, onToggle, className = "" }) {
610
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { role: "group", className: `flex flex-wrap gap-2 ${className}`.trim(), children: labels.map((label, day) => {
611
+ const active = selected.includes(day);
612
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
613
+ "button",
614
+ {
615
+ type: "button",
616
+ "aria-pressed": active,
617
+ onClick: () => onToggle(day),
618
+ className: `flex h-10 w-10 items-center justify-center rounded-full border text-xs font-semibold transition-colors ${active ? "border-brand-primary bg-brand-primary text-white" : "border-border text-text-secondary hover:bg-surface-subtle"}`,
619
+ children: label
620
+ },
621
+ day
622
+ );
623
+ }) });
624
+ }
625
+
626
+ // src/molecules/SelectableCard/SelectableCard.tsx
627
+ var import_jsx_runtime16 = require("react/jsx-runtime");
628
+ function SelectableCard({ icon, title, subtitle, media, selected = false, onClick, className = "" }) {
629
+ const base2 = `w-full rounded-xl border text-left transition-colors ${selected ? "border-brand-primary bg-brand-primary/5" : "border-border hover:bg-surface-subtle"} ${className}`.trim();
630
+ if (media) {
631
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { type: "button", "aria-pressed": selected, onClick, className: `overflow-hidden ${base2}`, children: [
632
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "h-36 w-full overflow-hidden", children: media }),
633
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-3 p-4", children: [
634
+ icon && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
635
+ "span",
636
+ {
637
+ className: `flex h-8 w-8 shrink-0 items-center justify-center rounded-full ${selected ? "bg-brand-primary text-white" : "bg-surface-muted text-text-secondary"}`,
638
+ children: icon
639
+ }
640
+ ),
641
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "flex flex-col", children: [
642
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-medium text-text-primary", children: title }),
643
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-sm text-text-tertiary", children: subtitle })
644
+ ] })
645
+ ] })
646
+ ] });
647
+ }
648
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { type: "button", "aria-pressed": selected, onClick, className: `flex items-center gap-3 p-4 ${base2}`, children: [
649
+ icon && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
650
+ "span",
651
+ {
652
+ className: `flex h-10 w-10 shrink-0 items-center justify-center rounded-full ${selected ? "bg-brand-primary text-white" : "bg-surface-muted text-text-secondary"}`,
653
+ children: icon
654
+ }
655
+ ),
656
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "flex flex-col", children: [
657
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-medium text-text-primary", children: title }),
658
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-sm text-text-tertiary", children: subtitle })
659
+ ] })
660
+ ] });
661
+ }
662
+
663
+ // src/molecules/FileDropzone/FileDropzone.tsx
664
+ var import_react = require("react");
665
+ var import_jsx_runtime17 = require("react/jsx-runtime");
666
+ function FileDropzone({
667
+ accept,
668
+ onFileSelected,
669
+ selectedFileName,
670
+ label = "Arrastra tu archivo aqu\xED, o haz clic para elegirlo",
671
+ hint,
672
+ className = ""
673
+ }) {
674
+ const inputRef = (0, import_react.useRef)(null);
675
+ const [dragActive, setDragActive] = (0, import_react.useState)(false);
676
+ function openPicker() {
677
+ inputRef.current?.click();
678
+ }
679
+ function handleKeyDown(e) {
680
+ if (e.key === "Enter" || e.key === " ") {
681
+ e.preventDefault();
682
+ openPicker();
683
+ }
684
+ }
685
+ function handleDrop(e) {
686
+ e.preventDefault();
687
+ setDragActive(false);
688
+ onFileSelected(e.dataTransfer.files?.[0] ?? null);
689
+ }
690
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
691
+ "div",
692
+ {
693
+ role: "button",
694
+ tabIndex: 0,
695
+ onClick: openPicker,
696
+ onKeyDown: handleKeyDown,
697
+ onDragOver: (e) => {
698
+ e.preventDefault();
699
+ setDragActive(true);
700
+ },
701
+ onDragLeave: () => setDragActive(false),
702
+ onDrop: handleDrop,
703
+ className: `flex cursor-pointer flex-col items-center justify-center gap-2 rounded-xl border-2 border-dashed px-6 py-8 text-center transition-colors ${dragActive ? "border-brand-primary bg-brand-primary/5" : "border-border hover:border-brand-primary/60"} ${className}`.trim(),
704
+ children: [
705
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
706
+ "input",
707
+ {
708
+ ref: inputRef,
709
+ type: "file",
710
+ accept,
711
+ className: "hidden",
712
+ onChange: (e) => onFileSelected(e.target.files?.[0] ?? null)
713
+ }
714
+ ),
715
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(UploadIcon, { className: `size-6 ${dragActive ? "text-brand-primary" : "text-text-tertiary"}` }),
716
+ selectedFileName ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm font-medium text-text-primary", children: selectedFileName }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
717
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm font-medium text-text-primary", children: label }),
718
+ hint && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs text-text-tertiary", children: hint })
719
+ ] })
720
+ ]
721
+ }
722
+ );
723
+ }
724
+
725
+ // src/organisms/Sidebar/Sidebar.tsx
726
+ var import_jsx_runtime18 = require("react/jsx-runtime");
589
727
  function Sidebar({
590
728
  brandName = "Redinamic",
591
729
  stations,
@@ -595,43 +733,43 @@ function Sidebar({
595
733
  user,
596
734
  onLogout
597
735
  }) {
598
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("aside", { className: "fixed left-0 top-0 flex h-screen w-[260px] flex-col justify-between bg-brand-sidebar pb-2 pt-8", children: [
599
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-col gap-6 px-4 pb-6", children: [
600
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-3 px-2", children: [
601
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex size-8 items-center justify-center rounded bg-brand-logo", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(BoltIcon, { className: "size-4 text-brand-sidebar" }) }),
602
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-2xl font-semibold tracking-tight text-white", children: brandName })
736
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("aside", { className: "fixed left-0 top-0 flex h-screen w-[260px] flex-col justify-between bg-brand-sidebar pb-2 pt-8", children: [
737
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col gap-6 px-4 pb-6", children: [
738
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-3 px-2", children: [
739
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex size-8 items-center justify-center rounded bg-brand-logo", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(BoltIcon, { className: "size-4 text-brand-sidebar" }) }),
740
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-2xl font-semibold tracking-tight text-white", children: brandName })
603
741
  ] }),
604
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "relative", children: [
605
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MapPinIcon, { className: "pointer-events-none absolute left-4 top-1/2 size-4 -translate-y-1/2 text-white" }),
606
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
742
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "relative", children: [
743
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(MapPinIcon, { className: "pointer-events-none absolute left-4 top-1/2 size-4 -translate-y-1/2 text-white" }),
744
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
607
745
  "select",
608
746
  {
609
747
  value: selectedStationId,
610
748
  onChange: (event) => onSelectStation(event.target.value),
611
749
  className: "w-full appearance-none rounded-xl border border-white/10 bg-white/10 py-2.5 pl-10 pr-9 text-sm font-semibold text-white outline-none",
612
- children: stations.map((station) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: station.id, className: "text-text-primary", children: station.label }, station.id))
750
+ children: stations.map((station) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: station.id, className: "text-text-primary", children: station.label }, station.id))
613
751
  }
614
752
  ),
615
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChevronDownIcon, { className: "pointer-events-none absolute right-3 top-1/2 size-3 -translate-y-1/2 text-white" })
753
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChevronDownIcon, { className: "pointer-events-none absolute right-3 top-1/2 size-3 -translate-y-1/2 text-white" })
616
754
  ] })
617
755
  ] }),
618
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("nav", { className: "flex flex-1 flex-col gap-1 px-4", children: navItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(NavItem, { icon: item.icon, label: item.label, active: item.active, href: item.href }, item.key)) }),
619
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "border-t border-white/10 px-4 pt-4", children: [
620
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-3 px-4 py-3", children: [
621
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Avatar, { className: "bg-brand-primary text-white", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(UserCircleIcon, { className: "size-4" }) }),
622
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
623
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-sm font-semibold text-white", children: user.name }),
624
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-xs text-white/60", children: user.role })
756
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("nav", { className: "flex flex-1 flex-col gap-1 px-4", children: navItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(NavItem, { icon: item.icon, label: item.label, active: item.active, href: item.href }, item.key)) }),
757
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "border-t border-white/10 px-4 pt-4", children: [
758
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-3 px-4 py-3", children: [
759
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Avatar, { className: "bg-brand-primary text-white", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(UserCircleIcon, { className: "size-4" }) }),
760
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
761
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm font-semibold text-white", children: user.name }),
762
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-xs text-white/60", children: user.role })
625
763
  ] })
626
764
  ] }),
627
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
765
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
628
766
  "button",
629
767
  {
630
768
  type: "button",
631
769
  onClick: onLogout,
632
770
  className: "flex w-full items-center gap-3 rounded-lg px-4 py-2 text-sm font-semibold text-white/50 transition-colors hover:text-white/80",
633
771
  children: [
634
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(LogOutIcon, { className: "size-4" }),
772
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(LogOutIcon, { className: "size-4" }),
635
773
  "Cerrar Sesi\xF3n"
636
774
  ]
637
775
  }
@@ -641,7 +779,7 @@ function Sidebar({
641
779
  }
642
780
 
643
781
  // src/organisms/TopBar/TopBar.tsx
644
- var import_jsx_runtime16 = require("react/jsx-runtime");
782
+ var import_jsx_runtime19 = require("react/jsx-runtime");
645
783
  function TopBar({
646
784
  stationName,
647
785
  lastUpdatedLabel,
@@ -649,36 +787,36 @@ function TopBar({
649
787
  refreshing = false,
650
788
  middleContent
651
789
  }) {
652
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: "fixed left-[260px] right-0 top-0 z-10 flex h-20 items-center justify-between gap-4 bg-surface-page/80 px-6 shadow-header backdrop-blur-md", children: [
653
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "shrink-0", children: [
654
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-2", children: [
655
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MapPinIcon, { className: "size-4 text-text-primary" }),
656
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-sm font-semibold text-text-primary", children: stationName })
790
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("header", { className: "fixed left-[260px] right-0 top-0 z-10 flex h-20 items-center justify-between gap-4 bg-surface-page/80 px-6 shadow-header backdrop-blur-md", children: [
791
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "shrink-0", children: [
792
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", children: [
793
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MapPinIcon, { className: "size-4 text-text-primary" }),
794
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-sm font-semibold text-text-primary", children: stationName })
657
795
  ] }),
658
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "mt-1 flex items-center gap-2", children: [
659
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "size-2 rounded-full bg-success-dark" }),
660
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs font-medium text-text-secondary", children: lastUpdatedLabel })
796
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "mt-1 flex items-center gap-2", children: [
797
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "size-2 rounded-full bg-success-dark" }),
798
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-xs font-medium text-text-secondary", children: lastUpdatedLabel })
661
799
  ] })
662
800
  ] }),
663
801
  middleContent,
664
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex shrink-0 items-center gap-4", children: [
665
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
802
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex shrink-0 items-center gap-4", children: [
803
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
666
804
  Button,
667
805
  {
668
806
  variant: "primary",
669
- icon: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(RefreshIcon, { className: `size-4 ${refreshing ? "animate-spin" : ""}` }),
807
+ icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(RefreshIcon, { className: `size-4 ${refreshing ? "animate-spin" : ""}` }),
670
808
  onClick: onRefresh,
671
809
  disabled: refreshing,
672
810
  children: "Actualizar datos"
673
811
  }
674
812
  ),
675
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Avatar, { className: "bg-brand-primary text-white", size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(UserCircleIcon, { className: "size-4" }) })
813
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Avatar, { className: "bg-brand-primary text-white", size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(UserCircleIcon, { className: "size-4" }) })
676
814
  ] })
677
815
  ] });
678
816
  }
679
817
 
680
818
  // src/organisms/ConfirmDialog/ConfirmDialog.tsx
681
- var import_jsx_runtime17 = require("react/jsx-runtime");
819
+ var import_jsx_runtime20 = require("react/jsx-runtime");
682
820
  function ConfirmDialog({
683
821
  open,
684
822
  onClose,
@@ -693,49 +831,49 @@ function ConfirmDialog({
693
831
  confirming = false
694
832
  }) {
695
833
  if (!open) return null;
696
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "w-full max-w-md overflow-hidden rounded-2xl bg-white shadow-modal", children: [
697
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "relative flex items-center justify-center bg-gradient-to-r from-brand-primary to-info-dark py-8", children: [
698
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
834
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "w-full max-w-md overflow-hidden rounded-2xl bg-white shadow-modal", children: [
835
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "relative flex items-center justify-center bg-gradient-to-r from-brand-primary to-info-dark py-8", children: [
836
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
699
837
  "button",
700
838
  {
701
839
  type: "button",
702
840
  onClick: onClose,
703
841
  "aria-label": "Cerrar",
704
842
  className: "absolute right-4 top-4 text-white/80 hover:text-white",
705
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(XIcon, { className: "size-5" })
843
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(XIcon, { className: "size-5" })
706
844
  }
707
845
  ),
708
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex size-14 items-center justify-center rounded-full bg-white text-brand-primary", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(WalletIcon, { className: "size-6" }) })
846
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex size-14 items-center justify-center rounded-full bg-white text-brand-primary", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(WalletIcon, { className: "size-6" }) })
709
847
  ] }),
710
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex flex-col items-center gap-3 px-8 py-6 text-center", children: [
711
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h2", { className: "text-xl font-bold text-text-primary", children: title }),
712
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "rounded-full bg-surface-muted px-3 py-1 text-xs font-semibold text-text-secondary", children: productLabel }),
713
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm text-text-secondary", children: description }),
714
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "mt-2 flex w-full items-center justify-between rounded-xl bg-surface-subtle p-4", children: [
715
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "text-left", children: [
716
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs uppercase text-text-secondary", children: "Actual" }),
717
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-lg font-semibold text-text-tertiary line-through", children: currentPrice })
848
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col items-center gap-3 px-8 py-6 text-center", children: [
849
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h2", { className: "text-xl font-bold text-text-primary", children: title }),
850
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "rounded-full bg-surface-muted px-3 py-1 text-xs font-semibold text-text-secondary", children: productLabel }),
851
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-text-secondary", children: description }),
852
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "mt-2 flex w-full items-center justify-between rounded-xl bg-surface-subtle p-4", children: [
853
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "text-left", children: [
854
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs uppercase text-text-secondary", children: "Actual" }),
855
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-lg font-semibold text-text-tertiary line-through", children: currentPrice })
718
856
  ] }),
719
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-text-secondary", children: "\u2192" }),
720
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "text-right", children: [
721
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs uppercase text-success-dark", children: "Recomendado" }),
722
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-lg font-semibold text-brand-primary", children: newPrice })
857
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-text-secondary", children: "\u2192" }),
858
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "text-right", children: [
859
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs uppercase text-success-dark", children: "Recomendado" }),
860
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-lg font-semibold text-brand-primary", children: newPrice })
723
861
  ] })
724
862
  ] }),
725
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex w-full items-center justify-between text-sm", children: [
726
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "text-left", children: [
727
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs text-text-secondary", children: "Impacto en Margen" }),
728
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "font-semibold text-success-dark", children: marginImpactLabel })
863
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex w-full items-center justify-between text-sm", children: [
864
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "text-left", children: [
865
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs text-text-secondary", children: "Impacto en Margen" }),
866
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "font-semibold text-success-dark", children: marginImpactLabel })
729
867
  ] }),
730
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "text-right", children: [
731
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs text-text-secondary", children: "Volumen Estimado" }),
732
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "font-semibold text-success-dark", children: volumeImpactLabel })
868
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "text-right", children: [
869
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs text-text-secondary", children: "Volumen Estimado" }),
870
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "font-semibold text-success-dark", children: volumeImpactLabel })
733
871
  ] })
734
872
  ] })
735
873
  ] }),
736
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-end gap-4 border-t border-border px-8 py-4", children: [
737
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Button, { variant: "text", onClick: onClose, children: "Cancelar" }),
738
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Button, { variant: "primary", onClick: onConfirm, disabled: confirming, children: confirming ? "Aplicando..." : "Confirmar y aplicar" })
874
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center justify-end gap-4 border-t border-border px-8 py-4", children: [
875
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { variant: "text", onClick: onClose, children: "Cancelar" }),
876
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { variant: "primary", onClick: onConfirm, disabled: confirming, children: confirming ? "Aplicando..." : "Confirmar y aplicar" })
739
877
  ] })
740
878
  ] }) });
741
879
  }
@@ -747,12 +885,14 @@ function ConfirmDialog({
747
885
  Badge,
748
886
  BoltIcon,
749
887
  Button,
888
+ CalendarIcon,
750
889
  Card,
751
890
  CheckCircleIcon,
752
891
  ChevronDownIcon,
753
892
  CompetitorRow,
754
893
  ConfirmDialog,
755
894
  DecisionFactorRow,
895
+ FileDropzone,
756
896
  FuelIcon,
757
897
  FuelPumpSolidIcon,
758
898
  LogOutIcon,
@@ -763,6 +903,7 @@ function ConfirmDialog({
763
903
  ProgressBar,
764
904
  RefreshIcon,
765
905
  SegmentedTabs,
906
+ SelectableCard,
766
907
  Sidebar,
767
908
  Snackbar,
768
909
  StatTile,
@@ -772,9 +913,11 @@ function ConfirmDialog({
772
913
  TrendDownIcon,
773
914
  TrendUpIcon,
774
915
  TrendUpSolidIcon,
916
+ UploadIcon,
775
917
  UserCircleIcon,
776
918
  WalletIcon,
777
919
  WalletSolidIcon,
920
+ WeekdayPicker,
778
921
  XIcon,
779
922
  colors
780
923
  });