@soulbatical/tetra-ui 0.1.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.
Files changed (123) hide show
  1. package/dist/components/AutoCard.d.ts +41 -0
  2. package/dist/components/AutoCard.d.ts.map +1 -0
  3. package/dist/components/AutoCard.js +73 -0
  4. package/dist/components/AutoCard.js.map +1 -0
  5. package/dist/components/CookieConsent.d.ts +15 -0
  6. package/dist/components/CookieConsent.d.ts.map +1 -0
  7. package/dist/components/CookieConsent.js +27 -0
  8. package/dist/components/CookieConsent.js.map +1 -0
  9. package/dist/components/GenericListLayout.d.ts +48 -0
  10. package/dist/components/GenericListLayout.d.ts.map +1 -0
  11. package/dist/components/GenericListLayout.js +18 -0
  12. package/dist/components/GenericListLayout.js.map +1 -0
  13. package/dist/components/ListGenerator.d.ts +41 -0
  14. package/dist/components/ListGenerator.d.ts.map +1 -0
  15. package/dist/components/ListGenerator.js +40 -0
  16. package/dist/components/ListGenerator.js.map +1 -0
  17. package/dist/components/LoadingStates.d.ts +38 -0
  18. package/dist/components/LoadingStates.d.ts.map +1 -0
  19. package/dist/components/LoadingStates.js +51 -0
  20. package/dist/components/LoadingStates.js.map +1 -0
  21. package/dist/components/OrgSwitcher.d.ts +15 -0
  22. package/dist/components/OrgSwitcher.d.ts.map +1 -0
  23. package/dist/components/OrgSwitcher.js +36 -0
  24. package/dist/components/OrgSwitcher.js.map +1 -0
  25. package/dist/components/PageHeader.d.ts +16 -0
  26. package/dist/components/PageHeader.d.ts.map +1 -0
  27. package/dist/components/PageHeader.js +10 -0
  28. package/dist/components/PageHeader.js.map +1 -0
  29. package/dist/components/ProtectedRoute.d.ts +9 -0
  30. package/dist/components/ProtectedRoute.d.ts.map +1 -0
  31. package/dist/components/ProtectedRoute.js +30 -0
  32. package/dist/components/ProtectedRoute.js.map +1 -0
  33. package/dist/components/StatusBadge.d.ts +15 -0
  34. package/dist/components/StatusBadge.d.ts.map +1 -0
  35. package/dist/components/StatusBadge.js +79 -0
  36. package/dist/components/StatusBadge.js.map +1 -0
  37. package/dist/components/ThemeToggle.d.ts +14 -0
  38. package/dist/components/ThemeToggle.d.ts.map +1 -0
  39. package/dist/components/ThemeToggle.js +20 -0
  40. package/dist/components/ThemeToggle.js.map +1 -0
  41. package/dist/hooks/use-mobile.d.ts +2 -0
  42. package/dist/hooks/use-mobile.d.ts.map +1 -0
  43. package/dist/hooks/use-mobile.js +17 -0
  44. package/dist/hooks/use-mobile.js.map +1 -0
  45. package/dist/hooks/useAuth.d.ts +34 -0
  46. package/dist/hooks/useAuth.d.ts.map +1 -0
  47. package/dist/hooks/useAuth.js +156 -0
  48. package/dist/hooks/useAuth.js.map +1 -0
  49. package/dist/hooks/useCacheInvalidation.d.ts +25 -0
  50. package/dist/hooks/useCacheInvalidation.d.ts.map +1 -0
  51. package/dist/hooks/useCacheInvalidation.js +57 -0
  52. package/dist/hooks/useCacheInvalidation.js.map +1 -0
  53. package/dist/hooks/useDebounce.d.ts +2 -0
  54. package/dist/hooks/useDebounce.d.ts.map +1 -0
  55. package/dist/hooks/useDebounce.js +15 -0
  56. package/dist/hooks/useDebounce.js.map +1 -0
  57. package/dist/hooks/useDialog.d.ts +26 -0
  58. package/dist/hooks/useDialog.d.ts.map +1 -0
  59. package/dist/hooks/useDialog.js +37 -0
  60. package/dist/hooks/useDialog.js.map +1 -0
  61. package/dist/hooks/useFilterConfigs.d.ts +81 -0
  62. package/dist/hooks/useFilterConfigs.d.ts.map +1 -0
  63. package/dist/hooks/useFilterConfigs.js +68 -0
  64. package/dist/hooks/useFilterConfigs.js.map +1 -0
  65. package/dist/hooks/useFormSubmit.d.ts +79 -0
  66. package/dist/hooks/useFormSubmit.d.ts.map +1 -0
  67. package/dist/hooks/useFormSubmit.js +57 -0
  68. package/dist/hooks/useFormSubmit.js.map +1 -0
  69. package/dist/hooks/useGenericList.d.ts +62 -0
  70. package/dist/hooks/useGenericList.d.ts.map +1 -0
  71. package/dist/hooks/useGenericList.js +75 -0
  72. package/dist/hooks/useGenericList.js.map +1 -0
  73. package/dist/hooks/useGenericListWithConfig.d.ts +65 -0
  74. package/dist/hooks/useGenericListWithConfig.d.ts.map +1 -0
  75. package/dist/hooks/useGenericListWithConfig.js +98 -0
  76. package/dist/hooks/useGenericListWithConfig.js.map +1 -0
  77. package/dist/hooks/useInfiniteScroll.d.ts +11 -0
  78. package/dist/hooks/useInfiniteScroll.d.ts.map +1 -0
  79. package/dist/hooks/useInfiniteScroll.js +63 -0
  80. package/dist/hooks/useInfiniteScroll.js.map +1 -0
  81. package/dist/hooks/useOrganizations.d.ts +27 -0
  82. package/dist/hooks/useOrganizations.d.ts.map +1 -0
  83. package/dist/hooks/useOrganizations.js +56 -0
  84. package/dist/hooks/useOrganizations.js.map +1 -0
  85. package/dist/hooks/usePageContext.d.ts +29 -0
  86. package/dist/hooks/usePageContext.d.ts.map +1 -0
  87. package/dist/hooks/usePageContext.js +32 -0
  88. package/dist/hooks/usePageContext.js.map +1 -0
  89. package/dist/hooks/usePersistedQueryState.d.ts +35 -0
  90. package/dist/hooks/usePersistedQueryState.d.ts.map +1 -0
  91. package/dist/hooks/usePersistedQueryState.js +187 -0
  92. package/dist/hooks/usePersistedQueryState.js.map +1 -0
  93. package/dist/hooks/useQueryState.d.ts +40 -0
  94. package/dist/hooks/useQueryState.d.ts.map +1 -0
  95. package/dist/hooks/useQueryState.js +246 -0
  96. package/dist/hooks/useQueryState.js.map +1 -0
  97. package/dist/index.d.ts +30 -0
  98. package/dist/index.d.ts.map +1 -0
  99. package/dist/index.js +43 -0
  100. package/dist/index.js.map +1 -0
  101. package/dist/lib/utils.d.ts +3 -0
  102. package/dist/lib/utils.d.ts.map +1 -0
  103. package/dist/lib/utils.js +6 -0
  104. package/dist/lib/utils.js.map +1 -0
  105. package/dist/providers/QueryProvider.d.ts +9 -0
  106. package/dist/providers/QueryProvider.d.ts.map +1 -0
  107. package/dist/providers/QueryProvider.js +20 -0
  108. package/dist/providers/QueryProvider.js.map +1 -0
  109. package/dist/providers/ThemeProvider.d.ts +15 -0
  110. package/dist/providers/ThemeProvider.d.ts.map +1 -0
  111. package/dist/providers/ThemeProvider.js +13 -0
  112. package/dist/providers/ThemeProvider.js.map +1 -0
  113. package/dist/services/apiClient.d.ts +20 -0
  114. package/dist/services/apiClient.d.ts.map +1 -0
  115. package/dist/services/apiClient.js +85 -0
  116. package/dist/services/apiClient.js.map +1 -0
  117. package/dist/types/index.d.ts +119 -0
  118. package/dist/types/index.d.ts.map +1 -0
  119. package/dist/types/index.js +5 -0
  120. package/dist/types/index.js.map +1 -0
  121. package/package.json +68 -0
  122. package/src/styles/dark-mode.css +135 -0
  123. package/src/styles/theme.css +105 -0
@@ -0,0 +1,41 @@
1
+ import type { ComponentType, AnchorHTMLAttributes } from 'react';
2
+ interface CardConfig {
3
+ title: {
4
+ template: string;
5
+ fallback: string;
6
+ };
7
+ detailPath?: string;
8
+ image?: {
9
+ field: string;
10
+ fallbackField?: string;
11
+ aspectRatio?: string;
12
+ fallbackIcon?: string;
13
+ };
14
+ badges?: Array<{
15
+ field: string;
16
+ variantMap?: Record<string, string>;
17
+ label?: string;
18
+ template?: string;
19
+ }>;
20
+ metadata?: Array<{
21
+ type: string;
22
+ field?: string;
23
+ format?: string;
24
+ label?: string;
25
+ icon?: string;
26
+ template?: string;
27
+ }>;
28
+ }
29
+ type LinkComponent = ComponentType<AnchorHTMLAttributes<HTMLAnchorElement> & {
30
+ href: string;
31
+ }>;
32
+ interface AutoCardProps {
33
+ item: Record<string, any>;
34
+ config: CardConfig;
35
+ feature: string;
36
+ /** Custom link component (e.g. Next.js Link). Defaults to <a> tag. */
37
+ LinkWrapper?: LinkComponent;
38
+ }
39
+ export declare function AutoCard({ item, config, feature, LinkWrapper }: AutoCardProps): import("react/jsx-runtime").JSX.Element;
40
+ export type { CardConfig, AutoCardProps, LinkComponent };
41
+ //# sourceMappingURL=AutoCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutoCard.d.ts","sourceRoot":"","sources":["../../src/components/AutoCard.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAIjE,UAAU,UAAU;IAClB,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,MAAM,CAAC,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACpC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;CACJ;AAED,KAAK,aAAa,GAAG,aAAa,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE/F,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B;AA4CD,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,aAAa,2CAiF7E;AAED,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ // ─── Badge styles (dark mode handled by @tetra/ui dark-mode.css) ──
4
+ const badgeStyles = {
5
+ default: 'bg-blue-100 text-blue-700',
6
+ secondary: 'bg-gray-100 text-gray-600',
7
+ outline: 'border border-gray-300 text-gray-500',
8
+ destructive: 'bg-red-100 text-red-700',
9
+ success: 'bg-green-100 text-green-700',
10
+ };
11
+ // ─── Helpers ─────────────────────────────────────────────────
12
+ /** Resolve a {{field}} template against an item */
13
+ function resolveTemplate(template, item) {
14
+ return template.replace(/\{\{(\w+)\}\}/g, (_, key) => {
15
+ const val = item[key];
16
+ return val != null ? String(val) : '';
17
+ });
18
+ }
19
+ function formatValue(type, value, format) {
20
+ if (value == null)
21
+ return '';
22
+ if (type === 'date') {
23
+ const d = new Date(value);
24
+ if (format === 'relative') {
25
+ const now = Date.now();
26
+ const diff = now - d.getTime();
27
+ const days = Math.floor(diff / 86400000);
28
+ if (days === 0)
29
+ return 'Today';
30
+ if (days === 1)
31
+ return 'Yesterday';
32
+ if (days < 7)
33
+ return `${days}d ago`;
34
+ return d.toLocaleDateString('nl-NL');
35
+ }
36
+ return d.toLocaleDateString('nl-NL');
37
+ }
38
+ return String(value);
39
+ }
40
+ // ─── Component ───────────────────────────────────────────────
41
+ export function AutoCard({ item, config, feature, LinkWrapper }) {
42
+ const title = resolveTemplate(config.title.template, item) || config.title.fallback;
43
+ const Anchor = LinkWrapper ?? 'a';
44
+ return (_jsxs(Anchor, { href: config.detailPath
45
+ ? resolveTemplate(config.detailPath, item)
46
+ : `/${feature}/${item.id}`, className: "block rounded-lg border border-gray-200 bg-white p-4 shadow-sm hover:shadow-md transition-shadow", children: [config.image && item[config.image.field] && (_jsx("img", { src: item[config.image.field], alt: title, className: "mb-3 w-full rounded-md object-cover", style: {
47
+ aspectRatio: config.image.aspectRatio === '16:9' ? '16/9'
48
+ : config.image.aspectRatio === '4:3' ? '4/3'
49
+ : config.image.aspectRatio === 'square' ? '1/1'
50
+ : 'auto',
51
+ } })), _jsx("h3", { className: "text-sm font-semibold text-gray-900 truncate", children: title }), config.badges && config.badges.length > 0 && (_jsx("div", { className: "mt-2 flex flex-wrap gap-1.5", children: config.badges.map((badge, i) => {
52
+ const value = item[badge.field];
53
+ if (value == null)
54
+ return null;
55
+ const displayValue = badge.template
56
+ ? resolveTemplate(badge.template, item)
57
+ : String(value);
58
+ const variant = badge.variantMap?.[value] || 'default';
59
+ const style = badgeStyles[variant] || badgeStyles.default;
60
+ return (_jsx("span", { className: `inline-block rounded-full px-2 py-0.5 text-xs font-medium capitalize ${style}`, children: badge.label ? `${badge.label}: ${displayValue}` : displayValue }, i));
61
+ }) })), config.metadata && config.metadata.length > 0 && (_jsx("div", { className: "mt-3 space-y-1", children: config.metadata.map((meta, i) => {
62
+ const value = meta.field ? item[meta.field] : null;
63
+ if (value == null && !meta.template)
64
+ return null;
65
+ const displayValue = meta.template
66
+ ? resolveTemplate(meta.template, item)
67
+ : formatValue(meta.type, value, meta.format);
68
+ if (!displayValue)
69
+ return null;
70
+ return (_jsxs("p", { className: "text-xs text-gray-500 truncate", children: [meta.label && (_jsxs("span", { className: "font-medium text-gray-400", children: [meta.label, ": "] })), displayValue] }, i));
71
+ }) }))] }));
72
+ }
73
+ //# sourceMappingURL=AutoCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutoCard.js","sourceRoot":"","sources":["../../src/components/AutoCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ interface CookieConsentProps {
2
+ /** localStorage key for consent state (default: "cookie_consent") */
3
+ storageKey?: string;
4
+ /** Text shown in the banner */
5
+ message?: string;
6
+ /** Link to privacy policy page */
7
+ privacyUrl?: string;
8
+ /** Called when user accepts cookies */
9
+ onAccept?: () => void;
10
+ /** Called when user declines cookies */
11
+ onDecline?: () => void;
12
+ }
13
+ export declare function CookieConsent({ storageKey, message, privacyUrl, onAccept, onDecline, }: CookieConsentProps): import("react/jsx-runtime").JSX.Element | null;
14
+ export type { CookieConsentProps };
15
+ //# sourceMappingURL=CookieConsent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CookieConsent.d.ts","sourceRoot":"","sources":["../../src/components/CookieConsent.tsx"],"names":[],"mappings":"AAMA,UAAU,kBAAkB;IAC1B,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAID,wBAAgB,aAAa,CAAC,EAC5B,UAA6B,EAC7B,OAAiF,EACjF,UAAuB,EACvB,QAAQ,EACR,SAAS,GACV,EAAE,kBAAkB,kDAkDpB;AAED,YAAY,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useEffect } from 'react';
4
+ // ─── Component ───────────────────────────────────────────────
5
+ export function CookieConsent({ storageKey = 'cookie_consent', message = 'We use cookies to measure ad performance and improve your experience.', privacyUrl = '/privacy', onAccept, onDecline, }) {
6
+ const [visible, setVisible] = useState(false);
7
+ useEffect(() => {
8
+ const consent = localStorage.getItem(storageKey);
9
+ if (!consent) {
10
+ setVisible(true);
11
+ }
12
+ }, [storageKey]);
13
+ function handleAccept() {
14
+ localStorage.setItem(storageKey, 'granted');
15
+ setVisible(false);
16
+ onAccept?.();
17
+ }
18
+ function handleDecline() {
19
+ localStorage.setItem(storageKey, 'denied');
20
+ setVisible(false);
21
+ onDecline?.();
22
+ }
23
+ if (!visible)
24
+ return null;
25
+ return (_jsx("div", { className: "fixed bottom-0 left-0 right-0 z-50 p-4 bg-gray-900 border-t border-gray-700", children: _jsxs("div", { className: "mx-auto max-w-4xl flex flex-col sm:flex-row items-center justify-between gap-4", children: [_jsxs("p", { className: "text-sm text-gray-300", children: [message, ' ', _jsx("a", { href: privacyUrl, className: "text-blue-400 underline hover:text-blue-300", children: "Privacy Policy" })] }), _jsxs("div", { className: "flex gap-3 shrink-0", children: [_jsx("button", { onClick: handleDecline, className: "rounded-md border border-gray-600 px-4 py-2 text-sm text-gray-300 hover:bg-gray-800 transition-colors", children: "Decline" }), _jsx("button", { onClick: handleAccept, className: "rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-500 transition-colors", children: "Accept" })] })] }) }));
26
+ }
27
+ //# sourceMappingURL=CookieConsent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CookieConsent.js","sourceRoot":"","sources":["../../src/components/CookieConsent.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAiB5C,gEAAgE;AAEhE,MAAM,UAAU,aAAa,CAAC,EAC5B,UAAU,GAAG,gBAAgB,EAC7B,OAAO,GAAG,uEAAuE,EACjF,UAAU,GAAG,UAAU,EACvB,QAAQ,EACR,SAAS,GACU;IACnB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,UAAU,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,SAAS,YAAY;QACnB,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC5C,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,QAAQ,EAAE,EAAE,CAAC;IACf,CAAC;IAED,SAAS,aAAa;QACpB,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC3C,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,SAAS,EAAE,EAAE,CAAC;IAChB,CAAC;IAED,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,OAAO,CACL,cAAK,SAAS,EAAC,6EAA6E,YAC1F,eAAK,SAAS,EAAC,gFAAgF,aAC7F,aAAG,SAAS,EAAC,uBAAuB,aACjC,OAAO,EAAE,GAAG,EACb,YAAG,IAAI,EAAE,UAAU,EAAE,SAAS,EAAC,6CAA6C,+BAExE,IACF,EACJ,eAAK,SAAS,EAAC,qBAAqB,aAClC,iBACE,OAAO,EAAE,aAAa,EACtB,SAAS,EAAC,uGAAuG,wBAG1G,EACT,iBACE,OAAO,EAAE,YAAY,EACrB,SAAS,EAAC,qGAAqG,uBAGxG,IACL,IACF,GACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,48 @@
1
+ import React, { type ReactNode } from "react";
2
+ interface SortOption {
3
+ value: string;
4
+ label: string;
5
+ }
6
+ interface GenericListLayoutProps {
7
+ /** Page title */
8
+ title: string;
9
+ /** Sort configuration (optional — hide sort dropdown when not provided) */
10
+ sortBy?: string;
11
+ sortOptions?: SortOption[];
12
+ onSortChange?: (value: string) => void;
13
+ /** Create button */
14
+ createButtonLabel?: string;
15
+ onCreateClick?: () => void;
16
+ /** Additional header actions (e.g., view toggles) */
17
+ additionalHeaderActions?: ReactNode;
18
+ headerActions?: ReactNode;
19
+ /** Filter section (optional) */
20
+ filterComponent?: ReactNode;
21
+ /** List section */
22
+ listComponent: ReactNode;
23
+ /** Loading states */
24
+ isLoading?: boolean;
25
+ itemsCount?: number;
26
+ /** Infinite scroll sentinel */
27
+ hasMore?: boolean;
28
+ sentinelRef?: React.RefObject<HTMLDivElement> | ((node: HTMLDivElement | null) => void);
29
+ isFetchingNextPage?: boolean;
30
+ totalCount?: number;
31
+ /** Label for the entity type, e.g. "orders", "HD charts" */
32
+ entityName?: string;
33
+ }
34
+ /**
35
+ * GenericListLayout — Universal layout for list pages.
36
+ *
37
+ * Provides consistent structure for:
38
+ * - Page header with title + sort + create button
39
+ * - Filter section
40
+ * - List section with loading overlay
41
+ * - Infinite scroll sentinel
42
+ *
43
+ * Uses plain HTML + Tailwind (no shadcn/ui dependency).
44
+ * Ported from SparkBuddy shared components.
45
+ */
46
+ export declare function GenericListLayout({ title, sortBy, sortOptions, onSortChange, createButtonLabel, onCreateClick, additionalHeaderActions, headerActions, filterComponent, listComponent, isLoading, itemsCount, hasMore, sentinelRef, isFetchingNextPage, totalCount, entityName, }: GenericListLayoutProps): import("react/jsx-runtime").JSX.Element;
47
+ export type { SortOption, GenericListLayoutProps };
48
+ //# sourceMappingURL=GenericListLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GenericListLayout.d.ts","sourceRoot":"","sources":["../../src/components/GenericListLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9C,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,sBAAsB;IAC9B,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IAEd,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEvC,oBAAoB;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAE3B,qDAAqD;IACrD,uBAAuB,CAAC,EAAE,SAAS,CAAC;IACpC,aAAa,CAAC,EAAE,SAAS,CAAC;IAE1B,gCAAgC;IAChC,eAAe,CAAC,EAAE,SAAS,CAAC;IAE5B,mBAAmB;IACnB,aAAa,EAAE,SAAS,CAAC;IAEzB,qBAAqB;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC;IACxF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,MAAM,EACN,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,aAAa,EACb,eAAe,EACf,aAAa,EACb,SAAiB,EACjB,UAAc,EACd,OAAe,EACf,WAAW,EACX,kBAA0B,EAC1B,UAAU,EACV,UAAoB,GACrB,EAAE,sBAAsB,2CAuGxB;AAED,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ /**
4
+ * GenericListLayout — Universal layout for list pages.
5
+ *
6
+ * Provides consistent structure for:
7
+ * - Page header with title + sort + create button
8
+ * - Filter section
9
+ * - List section with loading overlay
10
+ * - Infinite scroll sentinel
11
+ *
12
+ * Uses plain HTML + Tailwind (no shadcn/ui dependency).
13
+ * Ported from SparkBuddy shared components.
14
+ */
15
+ export function GenericListLayout({ title, sortBy, sortOptions, onSortChange, createButtonLabel, onCreateClick, additionalHeaderActions, headerActions, filterComponent, listComponent, isLoading = false, itemsCount = 0, hasMore = false, sentinelRef, isFetchingNextPage = false, totalCount, entityName = "items", }) {
16
+ return (_jsxs("div", { className: "p-8", children: [_jsxs("div", { className: "flex justify-between items-center mb-6", children: [_jsx("h1", { className: "text-3xl font-bold", children: title }), _jsxs("div", { className: "flex items-center gap-4", children: [additionalHeaderActions, headerActions, sortOptions && sortBy && onSortChange && (_jsx("select", { value: sortBy, onChange: (e) => onSortChange(e.target.value), className: "hidden lg:flex h-10 w-[180px] rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", children: sortOptions.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value))) })), createButtonLabel && onCreateClick && (_jsxs("button", { onClick: onCreateClick, className: "inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 transition-colors", children: [_jsx("svg", { className: "mr-2 h-4 w-4", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4.5v15m7.5-7.5h-15" }) }), createButtonLabel] }))] })] }), filterComponent && (_jsxs("div", { className: "relative", children: [filterComponent, isLoading && itemsCount === 0 && (_jsxs("div", { className: "absolute top-2 right-2 flex items-center text-sm text-gray-500", children: [_jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-primary mr-2" }), _jsx("span", { children: "Loading..." })] }))] })), _jsxs("div", { className: "relative", children: [listComponent, isLoading && itemsCount === 0 && (_jsx("div", { className: "absolute inset-0 bg-gray-50/90 backdrop-blur-sm flex items-center justify-center min-h-[200px]", children: _jsxs("div", { className: "flex flex-col items-center", children: [_jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-primary mb-2" }), _jsxs("span", { className: "text-gray-600", children: ["Loading ", entityName, "..."] })] }) }))] }), _jsxs("div", { className: "flex flex-col items-center py-8 space-y-2", children: [totalCount !== undefined && (_jsxs("div", { className: "text-sm text-gray-600", children: ["Showing ", itemsCount, " of ", totalCount, " ", entityName] })), hasMore && sentinelRef && (_jsxs(_Fragment, { children: [_jsx("div", { ref: sentinelRef, className: "h-1" }), isFetchingNextPage && (_jsxs("div", { className: "flex items-center space-x-2 text-gray-500", children: [_jsx("div", { className: "animate-spin rounded-full h-5 w-5 border-b-2 border-primary" }), _jsx("span", { children: "Loading more..." })] }))] }))] })] }));
17
+ }
18
+ //# sourceMappingURL=GenericListLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GenericListLayout.js","sourceRoot":"","sources":["../../src/components/GenericListLayout.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AA6Cb;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAChC,KAAK,EACL,MAAM,EACN,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,aAAa,EACb,eAAe,EACf,aAAa,EACb,SAAS,GAAG,KAAK,EACjB,UAAU,GAAG,CAAC,EACd,OAAO,GAAG,KAAK,EACf,WAAW,EACX,kBAAkB,GAAG,KAAK,EAC1B,UAAU,EACV,UAAU,GAAG,OAAO,GACG;IACvB,OAAO,CACL,eAAK,SAAS,EAAC,KAAK,aAElB,eAAK,SAAS,EAAC,wCAAwC,aACrD,aAAI,SAAS,EAAC,oBAAoB,YAAE,KAAK,GAAM,EAE/C,eAAK,SAAS,EAAC,yBAAyB,aAErC,uBAAuB,EACvB,aAAa,EAGb,WAAW,IAAI,MAAM,IAAI,YAAY,IAAI,CACxC,iBACE,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC7C,SAAS,EAAC,yLAAyL,YAElM,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC3B,iBAA2B,KAAK,EAAE,MAAM,CAAC,KAAK,YAC3C,MAAM,CAAC,KAAK,IADF,MAAM,CAAC,KAAK,CAEhB,CACV,CAAC,GACK,CACV,EAGA,iBAAiB,IAAI,aAAa,IAAI,CACrC,kBACE,OAAO,EAAE,aAAa,EACtB,SAAS,EAAC,kKAAkK,aAG5K,cACE,SAAS,EAAC,cAAc,EACxB,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,WAAW,EAAE,CAAC,EACd,MAAM,EAAC,cAAc,YAErB,eAAM,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,CAAC,EAAC,wBAAwB,GAAG,GAC5E,EACL,iBAAiB,IACX,CACV,IACG,IACF,EAGL,eAAe,IAAI,CAClB,eAAK,SAAS,EAAC,UAAU,aACtB,eAAe,EAGf,SAAS,IAAI,UAAU,KAAK,CAAC,IAAI,CAChC,eAAK,SAAS,EAAC,gEAAgE,aAC7E,cAAK,SAAS,EAAC,kEAAkE,GAAG,EACpF,wCAAuB,IACnB,CACP,IACG,CACP,EAGD,eAAK,SAAS,EAAC,UAAU,aACtB,aAAa,EAGb,SAAS,IAAI,UAAU,KAAK,CAAC,IAAI,CAChC,cAAK,SAAS,EAAC,gGAAgG,YAC7G,eAAK,SAAS,EAAC,4BAA4B,aACzC,cAAK,SAAS,EAAC,kEAAkE,GAAG,EACpF,gBAAM,SAAS,EAAC,eAAe,yBAAU,UAAU,WAAW,IAC1D,GACF,CACP,IACG,EAGN,eAAK,SAAS,EAAC,2CAA2C,aAEvD,UAAU,KAAK,SAAS,IAAI,CAC3B,eAAK,SAAS,EAAC,uBAAuB,yBAC3B,UAAU,UAAM,UAAU,OAAG,UAAU,IAC5C,CACP,EAGA,OAAO,IAAI,WAAW,IAAI,CACzB,8BACE,cAAK,GAAG,EAAE,WAAW,EAAE,SAAS,EAAC,KAAK,GAAG,EACxC,kBAAkB,IAAI,CACrB,eAAK,SAAS,EAAC,2CAA2C,aACxD,cAAK,SAAS,EAAC,6DAA6D,GAAG,EAC/E,6CAA4B,IACxB,CACP,IACA,CACJ,IACG,IACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,41 @@
1
+ import React from "react";
2
+ /**
3
+ * BaseGrid — Simple responsive grid with empty state.
4
+ * Inlined here to avoid external CSS dependency.
5
+ */
6
+ declare function BaseGrid({ children, emptyMessage, className, }: {
7
+ children: React.ReactNode;
8
+ emptyMessage?: string;
9
+ className?: string;
10
+ }): import("react/jsx-runtime").JSX.Element;
11
+ /**
12
+ * List Generator — Auto-generates list/grid components from backend config.
13
+ * Supports both grid and table layouts.
14
+ *
15
+ * Usage:
16
+ * const OrdersList = generateList(ordersFeatureConfig, OrderCard);
17
+ * <OrdersList items={orders} onRefresh={refetch} />
18
+ *
19
+ * Ported from SparkBuddy shared components.
20
+ */
21
+ export declare function generateList(config: {
22
+ tableName?: string;
23
+ display?: {
24
+ list?: {
25
+ type?: "grid" | "table";
26
+ emptyMessage?: string;
27
+ };
28
+ };
29
+ }, CardComponent: React.ComponentType<{
30
+ item: Record<string, unknown>;
31
+ onClick?: (id: string) => void;
32
+ onPhaseRefreshed?: () => void;
33
+ onAction?: (event: unknown) => void;
34
+ }>): ({ items, onRefresh, onItemClick, onAction, }: {
35
+ items: Record<string, unknown>[];
36
+ onRefresh?: () => void;
37
+ onItemClick?: (id: string) => void;
38
+ onAction?: (event: unknown) => void;
39
+ }) => import("react/jsx-runtime").JSX.Element;
40
+ export { BaseGrid };
41
+ //# sourceMappingURL=ListGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListGenerator.d.ts","sourceRoot":"","sources":["../../src/components/ListGenerator.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;GAGG;AACH,iBAAS,QAAQ,CAAC,EAChB,QAAQ,EACR,YAA+B,EAC/B,SAAc,GACf,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAkBA;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE;IACN,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE;YACL,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;YACxB,YAAY,CAAC,EAAE,MAAM,CAAC;SACvB,CAAC;KACH,CAAC;CACH,EACD,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC,CAAC,IAE4B,8CAK3B;IACD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC,6CA+BF;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import React from "react";
4
+ /**
5
+ * BaseGrid — Simple responsive grid with empty state.
6
+ * Inlined here to avoid external CSS dependency.
7
+ */
8
+ function BaseGrid({ children, emptyMessage = "No items found", className = "", }) {
9
+ const isEmpty = React.Children.count(children) === 0;
10
+ if (isEmpty) {
11
+ return (_jsx("div", { className: "flex items-center justify-center py-12 text-gray-500", children: emptyMessage }));
12
+ }
13
+ return (_jsx("div", { className: `grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 ${className}`.trim(), children: children }));
14
+ }
15
+ /**
16
+ * List Generator — Auto-generates list/grid components from backend config.
17
+ * Supports both grid and table layouts.
18
+ *
19
+ * Usage:
20
+ * const OrdersList = generateList(ordersFeatureConfig, OrderCard);
21
+ * <OrdersList items={orders} onRefresh={refetch} />
22
+ *
23
+ * Ported from SparkBuddy shared components.
24
+ */
25
+ export function generateList(config, CardComponent) {
26
+ return function GeneratedList({ items, onRefresh, onItemClick, onAction, }) {
27
+ const listConfig = config.display?.list;
28
+ if (!listConfig) {
29
+ return _jsxs("div", { children: ["List config missing for ", config.tableName] });
30
+ }
31
+ // Future: Support table layout
32
+ if (listConfig.type === "table") {
33
+ return (_jsx("div", { className: "text-center text-gray-500 py-8", children: "Table layout not yet implemented. Use 'grid' for now." }));
34
+ }
35
+ // Default: Grid layout
36
+ return (_jsx(BaseGrid, { emptyMessage: listConfig.emptyMessage || "No items found", children: items?.map((item) => (_jsx(CardComponent, { item: item, onClick: onItemClick, onPhaseRefreshed: onRefresh, onAction: onAction }, item.id))) }));
37
+ };
38
+ }
39
+ export { BaseGrid };
40
+ //# sourceMappingURL=ListGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListGenerator.js","sourceRoot":"","sources":["../../src/components/ListGenerator.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;GAGG;AACH,SAAS,QAAQ,CAAC,EAChB,QAAQ,EACR,YAAY,GAAG,gBAAgB,EAC/B,SAAS,GAAG,EAAE,GAKf;IACC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAErD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CACL,cAAK,SAAS,EAAC,sDAAsD,YAClE,YAAY,GACT,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,cACE,SAAS,EAAE,wDAAwD,SAAS,EAAE,CAAC,IAAI,EAAE,YAEpF,QAAQ,GACL,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAC1B,MAQC,EACD,aAKE;IAEF,OAAO,SAAS,aAAa,CAAC,EAC5B,KAAK,EACL,SAAS,EACT,WAAW,EACX,QAAQ,GAMT;QACC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC;QAExC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,sDAA8B,MAAM,CAAC,SAAS,IAAO,CAAC;QAC/D,CAAC;QAED,+BAA+B;QAC/B,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAChC,OAAO,CACL,cAAK,SAAS,EAAC,gCAAgC,sEAEzC,CACP,CAAC;QACJ,CAAC;QAED,uBAAuB;QACvB,OAAO,CACL,KAAC,QAAQ,IAAC,YAAY,EAAE,UAAU,CAAC,YAAY,IAAI,gBAAgB,YAChE,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACpB,KAAC,aAAa,IAEZ,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,SAAS,EAC3B,QAAQ,EAAE,QAAQ,IAJb,IAAI,CAAC,EAAY,CAKtB,CACH,CAAC,GACO,CACZ,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,38 @@
1
+ import React from "react";
2
+ interface LoadingCardProps {
3
+ title?: string;
4
+ message?: string;
5
+ size?: "sm" | "md" | "lg";
6
+ className?: string;
7
+ }
8
+ interface LoadingSpinnerProps {
9
+ message?: string;
10
+ size?: "sm" | "md" | "lg";
11
+ className?: string;
12
+ }
13
+ interface SkeletonProps {
14
+ lines?: number;
15
+ className?: string;
16
+ }
17
+ /**
18
+ * LoadingCard — Card with centered spinner and message.
19
+ * Uses plain HTML + Tailwind (no shadcn/ui Card dependency).
20
+ * Ported from SparkBuddy shared components.
21
+ */
22
+ export declare const LoadingCard: React.FC<LoadingCardProps>;
23
+ /**
24
+ * LoadingSpinner — Inline spinner with optional message.
25
+ */
26
+ export declare const LoadingSpinner: React.FC<LoadingSpinnerProps>;
27
+ /**
28
+ * Skeleton — Animated placeholder lines.
29
+ */
30
+ export declare const Skeleton: React.FC<SkeletonProps>;
31
+ /**
32
+ * SkeletonCard — Full card placeholder with skeleton lines.
33
+ */
34
+ export declare const SkeletonCard: React.FC<{
35
+ className?: string;
36
+ }>;
37
+ export {};
38
+ //# sourceMappingURL=LoadingStates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingStates.d.ts","sourceRoot":"","sources":["../../src/components/LoadingStates.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,mBAAmB;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoBD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAoClD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA4BxD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAiB5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAsBzD,CAAC"}
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ const sizeClasses = {
4
+ sm: {
5
+ icon: "h-4 w-4",
6
+ padding: "p-3",
7
+ text: "text-sm",
8
+ },
9
+ md: {
10
+ icon: "h-5 w-5",
11
+ padding: "p-4",
12
+ text: "text-base",
13
+ },
14
+ lg: {
15
+ icon: "h-6 w-6",
16
+ padding: "p-6",
17
+ text: "text-lg",
18
+ },
19
+ };
20
+ /**
21
+ * LoadingCard — Card with centered spinner and message.
22
+ * Uses plain HTML + Tailwind (no shadcn/ui Card dependency).
23
+ * Ported from SparkBuddy shared components.
24
+ */
25
+ export const LoadingCard = ({ title = "Loading...", message = "Please wait while we fetch the data.", size = "md", className = "", }) => {
26
+ const sizeClass = sizeClasses[size];
27
+ return (_jsxs("div", { className: `rounded-lg border bg-card text-card-foreground shadow-sm ${className}`, children: [_jsx("div", { className: `${sizeClass.padding} flex items-center justify-center`, children: _jsx("svg", { className: `${sizeClass.icon} animate-spin text-blue-600`, fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182" }) }) }), _jsxs("div", { className: `${sizeClass.padding} pt-0 text-center`, children: [_jsx("h3", { className: `${sizeClass.text} font-medium text-gray-900 mb-1`, children: title }), _jsx("p", { className: "text-sm text-gray-500", children: message })] })] }));
28
+ };
29
+ /**
30
+ * LoadingSpinner — Inline spinner with optional message.
31
+ */
32
+ export const LoadingSpinner = ({ message = "Loading...", size = "md", className = "", }) => {
33
+ const sizeClass = sizeClasses[size];
34
+ return (_jsxs("div", { className: `flex flex-col items-center justify-center space-y-2 ${className}`, children: [_jsx("svg", { className: `${sizeClass.icon} animate-spin text-blue-600`, fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 3a9 9 0 1 0 9 9" }) }), _jsx("p", { className: `${sizeClass.text} text-gray-600`, children: message })] }));
35
+ };
36
+ /**
37
+ * Skeleton — Animated placeholder lines.
38
+ */
39
+ export const Skeleton = ({ lines = 3, className = "", }) => {
40
+ return (_jsx("div", { className: `space-y-3 ${className}`, children: Array.from({ length: lines }).map((_, index) => {
41
+ const width = index === lines - 1 ? "w-3/4" : "w-full";
42
+ return (_jsx("div", { className: `h-4 bg-gray-200 rounded animate-pulse ${width}` }, index));
43
+ }) }));
44
+ };
45
+ /**
46
+ * SkeletonCard — Full card placeholder with skeleton lines.
47
+ */
48
+ export const SkeletonCard = ({ className = "", }) => {
49
+ return (_jsxs("div", { className: `rounded-lg border bg-card text-card-foreground shadow-sm ${className}`, children: [_jsx("div", { className: "p-6", children: _jsxs("div", { className: "flex items-center space-x-3", children: [_jsx("div", { className: "h-5 w-5 bg-gray-200 rounded animate-pulse" }), _jsx("div", { className: "h-5 w-32 bg-gray-200 rounded animate-pulse" })] }) }), _jsxs("div", { className: "p-6 pt-0 space-y-4", children: [_jsx(Skeleton, { lines: 4 }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(Skeleton, { lines: 2 }), _jsx(Skeleton, { lines: 2 })] })] })] }));
50
+ };
51
+ //# sourceMappingURL=LoadingStates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingStates.js","sourceRoot":"","sources":["../../src/components/LoadingStates.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Organization } from "../hooks/useOrganizations.js";
2
+ interface OrgSwitcherProps {
3
+ organizations: Organization[];
4
+ currentOrg: Organization | null;
5
+ onSwitch: (orgId: string) => void;
6
+ sidebar?: boolean;
7
+ }
8
+ /**
9
+ * Standard organization switcher dropdown.
10
+ * Shows current org name, opens dropdown to switch.
11
+ * Hidden when user has only 1 organization.
12
+ */
13
+ export declare function OrgSwitcher({ organizations, currentOrg, onSwitch, sidebar, }: OrgSwitcherProps): import("react/jsx-runtime").JSX.Element | null;
14
+ export {};
15
+ //# sourceMappingURL=OrgSwitcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrgSwitcher.d.ts","sourceRoot":"","sources":["../../src/components/OrgSwitcher.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,UAAU,gBAAgB;IACxB,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,UAAU,EAAE,YAAY,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACR,EAAE,gBAAgB,kDA6FlB"}
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useRef, useEffect } from "react";
4
+ /**
5
+ * Standard organization switcher dropdown.
6
+ * Shows current org name, opens dropdown to switch.
7
+ * Hidden when user has only 1 organization.
8
+ */
9
+ export function OrgSwitcher({ organizations, currentOrg, onSwitch, sidebar, }) {
10
+ const [open, setOpen] = useState(false);
11
+ const ref = useRef(null);
12
+ useEffect(() => {
13
+ function handleClickOutside(e) {
14
+ if (ref.current && !ref.current.contains(e.target)) {
15
+ setOpen(false);
16
+ }
17
+ }
18
+ document.addEventListener("mousedown", handleClickOutside);
19
+ return () => document.removeEventListener("mousedown", handleClickOutside);
20
+ }, []);
21
+ if (organizations.length <= 1) {
22
+ return currentOrg ? (_jsx("span", { className: `truncate text-sm text-gray-600 dark:text-gray-300 ${sidebar ? "block" : ""}`, children: currentOrg.name })) : null;
23
+ }
24
+ return (_jsxs("div", { className: "relative", ref: ref, children: [_jsxs("button", { onClick: () => setOpen(!open), className: `flex items-center gap-2 rounded-md text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-gray-700 dark:hover:text-white ${sidebar
25
+ ? "w-full justify-between px-3 py-2"
26
+ : "px-3 py-1.5"}`, children: [_jsx("span", { className: `truncate ${sidebar ? "max-w-[160px]" : "max-w-[150px]"}`, children: currentOrg?.name || "Select org" }), _jsx("svg", { className: "h-4 w-4 shrink-0", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9" }) })] }), open && (_jsx("div", { className: `absolute z-50 mt-1 rounded-md border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-700 dark:bg-gray-800 ${sidebar
27
+ ? "left-0 right-0 top-full"
28
+ : "left-0 top-full w-64"}`, children: organizations.map((org) => (_jsxs("button", { onClick: () => {
29
+ if (org.id !== currentOrg?.id)
30
+ onSwitch(org.id);
31
+ setOpen(false);
32
+ }, className: `flex w-full items-center justify-between text-left text-sm ${sidebar ? "px-3 py-2.5" : "px-4 py-2"} ${org.id === currentOrg?.id
33
+ ? "bg-gray-100 text-gray-900 dark:bg-gray-700 dark:text-white"
34
+ : "text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-gray-700 dark:hover:text-white"}`, children: [_jsx("span", { className: "truncate", children: org.name }), org.role && (_jsx("span", { className: "ml-2 shrink-0 rounded-full bg-gray-200 px-2 py-0.5 text-xs text-gray-500 dark:bg-gray-600 dark:text-gray-300", children: org.role }))] }, org.id))) }))] }));
35
+ }
36
+ //# sourceMappingURL=OrgSwitcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrgSwitcher.js","sourceRoot":"","sources":["../../src/components/OrgSwitcher.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAU3D;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACU;IACjB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEzC,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,kBAAkB,CAAC,CAAa;YACvC,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC,EAAE,CAAC;gBAC3D,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QAC3D,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAC7E,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC9B,OAAO,UAAU,CAAC,CAAC,CAAC,CAClB,eACE,SAAS,EAAE,qDACT,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EACtB,EAAE,YAED,UAAU,CAAC,IAAI,GACX,CACR,CAAC,CAAC,CAAC,IAAI,CAAC;IACX,CAAC;IAED,OAAO,CACL,eAAK,SAAS,EAAC,UAAU,EAAC,GAAG,EAAE,GAAG,aAChC,kBACE,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAC7B,SAAS,EAAE,kKACT,OAAO;oBACL,CAAC,CAAC,kCAAkC;oBACpC,CAAC,CAAC,aACN,EAAE,aAEF,eACE,SAAS,EAAE,YACT,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAC9B,EAAE,YAED,UAAU,EAAE,IAAI,IAAI,YAAY,GAC5B,EACP,cACE,SAAS,EAAC,kBAAkB,EAC5B,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,WAAW,EAAE,GAAG,EAChB,MAAM,EAAC,cAAc,YAErB,eACE,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,CAAC,EAAC,mDAAmD,GACrD,GACE,IACC,EAER,IAAI,IAAI,CACP,cACE,SAAS,EAAE,sHACT,OAAO;oBACL,CAAC,CAAC,yBAAyB;oBAC3B,CAAC,CAAC,sBACN,EAAE,YAED,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAC1B,kBAEE,OAAO,EAAE,GAAG,EAAE;wBACZ,IAAI,GAAG,CAAC,EAAE,KAAK,UAAU,EAAE,EAAE;4BAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;wBAChD,OAAO,CAAC,KAAK,CAAC,CAAC;oBACjB,CAAC,EACD,SAAS,EAAE,8DACT,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAC5B,IACE,GAAG,CAAC,EAAE,KAAK,UAAU,EAAE,EAAE;wBACvB,CAAC,CAAC,4DAA4D;wBAC9D,CAAC,CAAC,qHACN,EAAE,aAEF,eAAM,SAAS,EAAC,UAAU,YAAE,GAAG,CAAC,IAAI,GAAQ,EAC3C,GAAG,CAAC,IAAI,IAAI,CACX,eAAM,SAAS,EAAC,8GAA8G,YAC3H,GAAG,CAAC,IAAI,GACJ,CACR,KAlBI,GAAG,CAAC,EAAE,CAmBJ,CACV,CAAC,GACE,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+ interface PageHeaderProps {
3
+ title: string;
4
+ description?: string;
5
+ /** Any React component that accepts className */
6
+ icon?: React.ComponentType<{
7
+ className?: string;
8
+ }>;
9
+ }
10
+ /**
11
+ * PageHeader — Standard page header with title, optional icon, and description.
12
+ * Ported from SparkBuddy shared components.
13
+ */
14
+ export declare const PageHeader: React.FC<PageHeaderProps>;
15
+ export {};
16
+ //# sourceMappingURL=PageHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageHeader.d.ts","sourceRoot":"","sources":["../../src/components/PageHeader.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAgBhD,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * PageHeader — Standard page header with title, optional icon, and description.
5
+ * Ported from SparkBuddy shared components.
6
+ */
7
+ export const PageHeader = ({ title, description, icon: Icon, }) => {
8
+ return (_jsxs("div", { className: "mb-6", children: [_jsxs("div", { className: "flex items-center gap-3 mb-2", children: [Icon && _jsx(Icon, { className: "h-8 w-8 text-primary" }), _jsx("h1", { className: "text-3xl font-bold", children: title })] }), description && (_jsx("p", { className: "text-muted-foreground text-lg", children: description }))] }));
9
+ };
10
+ //# sourceMappingURL=PageHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageHeader.js","sourceRoot":"","sources":["../../src/components/PageHeader.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAWb;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAA8B,CAAC,EACpD,KAAK,EACL,WAAW,EACX,IAAI,EAAE,IAAI,GACX,EAAE,EAAE;IACH,OAAO,CACL,eAAK,SAAS,EAAC,MAAM,aACnB,eAAK,SAAS,EAAC,8BAA8B,aAC1C,IAAI,IAAI,KAAC,IAAI,IAAC,SAAS,EAAC,sBAAsB,GAAG,EAClD,aAAI,SAAS,EAAC,oBAAoB,YAAE,KAAK,GAAM,IAC3C,EACL,WAAW,IAAI,CACd,YAAG,SAAS,EAAC,+BAA+B,YAAE,WAAW,GAAK,CAC/D,IACG,CACP,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ /**
3
+ * Standard auth guard. Redirects to login if not authenticated.
4
+ * Wraps dashboard layouts.
5
+ */
6
+ export declare function ProtectedRoute({ children }: {
7
+ children: React.ReactNode;
8
+ }): import("react/jsx-runtime").JSX.Element | null;
9
+ //# sourceMappingURL=ProtectedRoute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProtectedRoute.d.ts","sourceRoot":"","sources":["../../src/components/ProtectedRoute.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAIzC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,kDA4BzE"}
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useEffect } from "react";
4
+ import { useRouter, usePathname } from "next/navigation.js";
5
+ import { useAuth } from "../hooks/useAuth.js";
6
+ /**
7
+ * Standard auth guard. Redirects to login if not authenticated.
8
+ * Wraps dashboard layouts.
9
+ */
10
+ export function ProtectedRoute({ children }) {
11
+ const { isAuthenticated, loading } = useAuth();
12
+ const router = useRouter();
13
+ const pathname = usePathname();
14
+ useEffect(() => {
15
+ if (!loading && !isAuthenticated) {
16
+ const returnTo = pathname && pathname !== "/"
17
+ ? `?returnTo=${encodeURIComponent(pathname)}`
18
+ : "";
19
+ router.push(`/auth/login${returnTo}`);
20
+ }
21
+ }, [loading, isAuthenticated, router, pathname]);
22
+ if (loading) {
23
+ return (_jsx("div", { className: "flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-gray-500 dark:text-gray-400", children: "Loading..." }) }));
24
+ }
25
+ if (!isAuthenticated) {
26
+ return null;
27
+ }
28
+ return _jsx(_Fragment, { children: children });
29
+ }
30
+ //# sourceMappingURL=ProtectedRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProtectedRoute.js","sourceRoot":"","sources":["../../src/components/ProtectedRoute.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAiC;IACxE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAE/B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC;YACjC,MAAM,QAAQ,GACZ,QAAQ,IAAI,QAAQ,KAAK,GAAG;gBAC1B,CAAC,CAAC,aAAa,kBAAkB,CAAC,QAAQ,CAAC,EAAE;gBAC7C,CAAC,CAAC,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEjD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CACL,cAAK,SAAS,EAAC,+CAA+C,YAC5D,cAAK,SAAS,EAAC,kCAAkC,2BAAiB,GAC9D,CACP,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,4BAAG,QAAQ,GAAI,CAAC;AACzB,CAAC"}