@donotdev/ui 0.0.10 → 0.0.11

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 (102) hide show
  1. package/dist/crud/components/EntityCardList.d.ts +16 -0
  2. package/dist/crud/components/EntityCardList.d.ts.map +1 -0
  3. package/dist/crud/components/EntityCardList.js +175 -0
  4. package/dist/crud/components/EntityDisplayRenderer.d.ts +13 -21
  5. package/dist/crud/components/EntityDisplayRenderer.d.ts.map +1 -1
  6. package/dist/crud/components/EntityDisplayRenderer.js +138 -23
  7. package/dist/crud/components/EntityFormRenderer.d.ts +18 -0
  8. package/dist/crud/components/EntityFormRenderer.d.ts.map +1 -0
  9. package/dist/crud/components/EntityFormRenderer.js +275 -0
  10. package/dist/crud/components/EntityList.d.ts +14 -0
  11. package/dist/crud/components/EntityList.d.ts.map +1 -0
  12. package/dist/crud/components/EntityList.js +201 -0
  13. package/dist/crud/components/index.d.ts +7 -5
  14. package/dist/crud/components/index.d.ts.map +1 -1
  15. package/dist/crud/components/index.js +6 -5
  16. package/dist/dndev.css +179 -0
  17. package/dist/index.js +4 -64
  18. package/dist/internal/layout/components/AutoMetaTags.d.ts.map +1 -1
  19. package/dist/internal/layout/components/AutoMetaTags.js +36 -6
  20. package/dist/internal/layout/components/NextJsAutoMetaTags.d.ts.map +1 -1
  21. package/dist/internal/layout/components/NextJsAutoMetaTags.js +38 -10
  22. package/dist/internal/layout/components/footer/FooterBranding.js +2 -2
  23. package/dist/styles/index.css +179 -0
  24. package/package.json +12 -12
  25. package/dist/crud/components/DisplayFieldRenderer.d.ts +0 -26
  26. package/dist/crud/components/DisplayFieldRenderer.d.ts.map +0 -1
  27. package/dist/crud/components/DisplayFieldRenderer.js +0 -107
  28. package/dist/crud/components/fields/display/AvatarFieldDisplay.d.ts +0 -23
  29. package/dist/crud/components/fields/display/AvatarFieldDisplay.d.ts.map +0 -1
  30. package/dist/crud/components/fields/display/AvatarFieldDisplay.js +0 -38
  31. package/dist/crud/components/fields/display/BadgeFieldDisplay.d.ts +0 -21
  32. package/dist/crud/components/fields/display/BadgeFieldDisplay.d.ts.map +0 -1
  33. package/dist/crud/components/fields/display/BadgeFieldDisplay.js +0 -31
  34. package/dist/crud/components/fields/display/ButtonFieldDisplay.d.ts +0 -29
  35. package/dist/crud/components/fields/display/ButtonFieldDisplay.d.ts.map +0 -1
  36. package/dist/crud/components/fields/display/ButtonFieldDisplay.js +0 -12
  37. package/dist/crud/components/fields/display/CheckboxFieldDisplay.d.ts +0 -21
  38. package/dist/crud/components/fields/display/CheckboxFieldDisplay.d.ts.map +0 -1
  39. package/dist/crud/components/fields/display/CheckboxFieldDisplay.js +0 -27
  40. package/dist/crud/components/fields/display/DateFieldDisplay.d.ts +0 -24
  41. package/dist/crud/components/fields/display/DateFieldDisplay.d.ts.map +0 -1
  42. package/dist/crud/components/fields/display/DateFieldDisplay.js +0 -41
  43. package/dist/crud/components/fields/display/DropdownDisplay.d.ts +0 -21
  44. package/dist/crud/components/fields/display/DropdownDisplay.d.ts.map +0 -1
  45. package/dist/crud/components/fields/display/DropdownDisplay.js +0 -25
  46. package/dist/crud/components/fields/display/FileFieldDisplay.d.ts +0 -21
  47. package/dist/crud/components/fields/display/FileFieldDisplay.d.ts.map +0 -1
  48. package/dist/crud/components/fields/display/FileFieldDisplay.js +0 -25
  49. package/dist/crud/components/fields/display/GeoPointFieldDisplay.d.ts +0 -25
  50. package/dist/crud/components/fields/display/GeoPointFieldDisplay.d.ts.map +0 -1
  51. package/dist/crud/components/fields/display/GeoPointFieldDisplay.js +0 -25
  52. package/dist/crud/components/fields/display/HiddenFieldDisplay.d.ts +0 -30
  53. package/dist/crud/components/fields/display/HiddenFieldDisplay.d.ts.map +0 -1
  54. package/dist/crud/components/fields/display/HiddenFieldDisplay.js +0 -12
  55. package/dist/crud/components/fields/display/ImageFieldDisplay.d.ts +0 -24
  56. package/dist/crud/components/fields/display/ImageFieldDisplay.d.ts.map +0 -1
  57. package/dist/crud/components/fields/display/ImageFieldDisplay.js +0 -38
  58. package/dist/crud/components/fields/display/LinkFieldDisplay.d.ts +0 -22
  59. package/dist/crud/components/fields/display/LinkFieldDisplay.d.ts.map +0 -1
  60. package/dist/crud/components/fields/display/LinkFieldDisplay.js +0 -48
  61. package/dist/crud/components/fields/display/MapFieldDisplay.d.ts +0 -25
  62. package/dist/crud/components/fields/display/MapFieldDisplay.d.ts.map +0 -1
  63. package/dist/crud/components/fields/display/MapFieldDisplay.js +0 -25
  64. package/dist/crud/components/fields/display/MultiDropdownDisplay.d.ts +0 -22
  65. package/dist/crud/components/fields/display/MultiDropdownDisplay.d.ts.map +0 -1
  66. package/dist/crud/components/fields/display/MultiDropdownDisplay.js +0 -25
  67. package/dist/crud/components/fields/display/MultiInputTextFieldDisplay.d.ts +0 -22
  68. package/dist/crud/components/fields/display/MultiInputTextFieldDisplay.d.ts.map +0 -1
  69. package/dist/crud/components/fields/display/MultiInputTextFieldDisplay.js +0 -25
  70. package/dist/crud/components/fields/display/NumberFieldDisplay.d.ts +0 -24
  71. package/dist/crud/components/fields/display/NumberFieldDisplay.d.ts.map +0 -1
  72. package/dist/crud/components/fields/display/NumberFieldDisplay.js +0 -28
  73. package/dist/crud/components/fields/display/PasswordFieldDisplay.d.ts +0 -24
  74. package/dist/crud/components/fields/display/PasswordFieldDisplay.d.ts.map +0 -1
  75. package/dist/crud/components/fields/display/PasswordFieldDisplay.js +0 -31
  76. package/dist/crud/components/fields/display/PhoneNumberDisplay.d.ts +0 -22
  77. package/dist/crud/components/fields/display/PhoneNumberDisplay.d.ts.map +0 -1
  78. package/dist/crud/components/fields/display/PhoneNumberDisplay.js +0 -25
  79. package/dist/crud/components/fields/display/RadioFieldDisplay.d.ts +0 -22
  80. package/dist/crud/components/fields/display/RadioFieldDisplay.d.ts.map +0 -1
  81. package/dist/crud/components/fields/display/RadioFieldDisplay.js +0 -25
  82. package/dist/crud/components/fields/display/RangeFieldDisplay.d.ts +0 -22
  83. package/dist/crud/components/fields/display/RangeFieldDisplay.d.ts.map +0 -1
  84. package/dist/crud/components/fields/display/RangeFieldDisplay.js +0 -25
  85. package/dist/crud/components/fields/display/ReferenceFieldDisplay.d.ts +0 -22
  86. package/dist/crud/components/fields/display/ReferenceFieldDisplay.d.ts.map +0 -1
  87. package/dist/crud/components/fields/display/ReferenceFieldDisplay.js +0 -26
  88. package/dist/crud/components/fields/display/RichTextDisplay.d.ts +0 -25
  89. package/dist/crud/components/fields/display/RichTextDisplay.d.ts.map +0 -1
  90. package/dist/crud/components/fields/display/RichTextDisplay.js +0 -104
  91. package/dist/crud/components/fields/display/TextAreaDisplay.d.ts +0 -22
  92. package/dist/crud/components/fields/display/TextAreaDisplay.d.ts.map +0 -1
  93. package/dist/crud/components/fields/display/TextAreaDisplay.js +0 -25
  94. package/dist/crud/components/fields/display/TextFieldDisplay.d.ts +0 -42
  95. package/dist/crud/components/fields/display/TextFieldDisplay.d.ts.map +0 -1
  96. package/dist/crud/components/fields/display/TextFieldDisplay.js +0 -97
  97. package/dist/crud/components/fields/display/TimestampFieldDisplay.d.ts +0 -22
  98. package/dist/crud/components/fields/display/TimestampFieldDisplay.d.ts.map +0 -1
  99. package/dist/crud/components/fields/display/TimestampFieldDisplay.js +0 -33
  100. package/dist/crud/components/fields/display/index.d.ts +0 -32
  101. package/dist/crud/components/fields/display/index.d.ts.map +0 -1
  102. package/dist/crud/components/fields/display/index.js +0 -32
@@ -1 +1 @@
1
- {"version":3,"file":"AutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/AutoMetaTags.tsx"],"names":[],"mappings":"AA0DA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAwC3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,aAoN1B,CAAC;AAEF;;;GAGG;AAEH,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"AutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/AutoMetaTags.tsx"],"names":[],"mappings":"AA0DA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAyE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,aAoN1B,CAAC;AAEF;;;GAGG;AAEH,eAAe,YAAY,CAAC"}
@@ -49,12 +49,34 @@ import { useMemo } from 'react';
49
49
  import { Helmet } from 'react-helmet-async';
50
50
  import { useTranslation, useIsClient } from '@donotdev/core';
51
51
  import { getDndevConfig } from '@donotdev/core';
52
- import { useSeoConfig, useAppConfig } from '@donotdev/core';
52
+ import { useSeoConfig, useAppConfig, getPlatformEnvVar } from '@donotdev/core';
53
53
  import { AssetResolver } from '@donotdev/ui';
54
54
  // Platform-specific hooks via conditional exports
55
55
  import { useLocation } from '@donotdev/ui/routing/hooks';
56
56
  /**
57
- * Get route metadata from window object (injected by build system)
57
+ * Match pathname against route path pattern (e.g. /cars/:id or /blog/:slug/comments/:id).
58
+ * Supports arbitrary nesting: any depth, any mix of static and :param segments.
59
+ */
60
+ function matchRoutePath(pattern, pathname) {
61
+ const patternSegments = pattern.split('/').filter(Boolean);
62
+ const pathnameSegments = pathname.split('/').filter(Boolean);
63
+ if (patternSegments.length !== pathnameSegments.length)
64
+ return false;
65
+ for (let i = 0; i < patternSegments.length; i++) {
66
+ const segment = patternSegments[i];
67
+ const pathSegment = pathnameSegments[i];
68
+ if (segment === undefined || pathSegment === undefined)
69
+ return false;
70
+ if (segment.startsWith(':'))
71
+ continue; // param matches any value
72
+ if (segment !== pathSegment)
73
+ return false;
74
+ }
75
+ return true;
76
+ }
77
+ /**
78
+ * Get route metadata from window object (injected by build system).
79
+ * Resolves dynamic routes by pattern (e.g. /cars/:id) so PageMeta (including namespace) is used for SEO.
58
80
  */
59
81
  function getRouteMetadata(pathname, isClient) {
60
82
  if (!isClient)
@@ -63,12 +85,20 @@ function getRouteMetadata(pathname, isClient) {
63
85
  const config = getDndevConfig();
64
86
  const routeData = config?.routes?.mapping;
65
87
  if (routeData && Array.isArray(routeData)) {
66
- const route = routeData.find((r) => r.path === pathname);
67
- if (route) {
88
+ // 1. Exact match (static routes)
89
+ let route = routeData.find((r) => r.path === pathname);
90
+ if (route)
91
+ return route.meta;
92
+ // 2. Pattern match (dynamic routes: /cars/:id, /blog/:slug/comments/:id, etc.)
93
+ const dynamicRoutes = routeData.filter((r) => typeof r.path === 'string' && r.path.includes(':'));
94
+ const matches = dynamicRoutes.filter((r) => matchRoutePath(r.path, pathname));
95
+ // Prefer most specific (longest path) so /blog/:slug/comments wins over /blog/:slug for /blog/a/comments
96
+ if (matches.length > 0) {
97
+ route = matches.reduce((best, r) => r.path.length > best.path.length ? r : best);
68
98
  return route.meta;
69
99
  }
70
100
  }
71
- // Extract potential namespace from path
101
+ // Fallback: first path segment as namespace (e.g. /cars/abc123 → ns: cars)
72
102
  const segments = pathname.split('/').filter(Boolean);
73
103
  if (segments.length > 0) {
74
104
  return { ns: segments[0] };
@@ -97,7 +127,7 @@ export const AutoMetaTags = () => {
97
127
  return null;
98
128
  const { defaultNamespace = 'home', defaultImage, twitterHandle, staticTags = {}, } = seoConfig;
99
129
  const siteName = useAppConfig('name');
100
- const baseUrl = useAppConfig('url');
130
+ const baseUrl = getPlatformEnvVar('APP_URL') || '';
101
131
  // Get route metadata
102
132
  const routeMeta = getRouteMetadata(location.pathname, isClient);
103
133
  // Memoize computed values for performance
@@ -1 +1 @@
1
- {"version":3,"file":"NextJsAutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/NextJsAutoMetaTags.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,UAAU,cAAc;IACtB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,UAAU,aAAa;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,uBAAuB;IAC/B,kCAAkC;IAClC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AA+BD;;;;;;;;GAQG;AACH,QAAA,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CA8L9D,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"NextJsAutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/NextJsAutoMetaTags.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,UAAU,cAAc;IACtB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,UAAU,aAAa;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,uBAAuB;IAC/B,kCAAkC;IAClC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AA+DD;;;;;;;;GAQG;AACH,QAAA,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CA8L9D,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -17,9 +17,31 @@ import { usePathname } from 'next/navigation';
17
17
  import { useMemo } from 'react';
18
18
  import { Helmet } from 'react-helmet-async';
19
19
  import { useTranslation, getDndevConfig, useIsClient } from '@donotdev/core';
20
- import { useAppConfig } from '@donotdev/core';
20
+ import { useAppConfig, getPlatformEnvVar } from '@donotdev/core';
21
21
  /**
22
- * Get route metadata from config (injected by build system)
22
+ * Match pathname against route path pattern (e.g. /cars/:id or /blog/:slug/comments/:id).
23
+ * Supports arbitrary nesting: any depth, any mix of static and :param segments.
24
+ */
25
+ function matchRoutePath(pattern, pathname) {
26
+ const patternSegments = pattern.split('/').filter(Boolean);
27
+ const pathnameSegments = pathname.split('/').filter(Boolean);
28
+ if (patternSegments.length !== pathnameSegments.length)
29
+ return false;
30
+ for (let i = 0; i < patternSegments.length; i++) {
31
+ const segment = patternSegments[i];
32
+ const pathSegment = pathnameSegments[i];
33
+ if (segment === undefined || pathSegment === undefined)
34
+ return false;
35
+ if (segment.startsWith(':'))
36
+ continue; // param matches any value
37
+ if (segment !== pathSegment)
38
+ return false;
39
+ }
40
+ return true;
41
+ }
42
+ /**
43
+ * Get route metadata from config (injected by build system).
44
+ * Resolves dynamic routes by pattern so PageMeta (including namespace) is used for SEO.
23
45
  */
24
46
  function getRouteMetadata(pathname, isClient) {
25
47
  if (!isClient)
@@ -28,16 +50,22 @@ function getRouteMetadata(pathname, isClient) {
28
50
  const config = getDndevConfig();
29
51
  const routeData = config?.routes?.mapping;
30
52
  if (routeData && Array.isArray(routeData)) {
31
- const route = routeData.find((r) => r.path === pathname);
53
+ // 1. Exact match (static routes)
54
+ let route = routeData.find((r) => r.path === pathname);
32
55
  if (route && route.meta) {
33
- // Map route.meta.namespace to routeMeta.ns
34
- return {
35
- ...route.meta,
36
- ns: route.meta.namespace, // Map namespace -> ns for compatibility
37
- };
56
+ return { ...route.meta, ns: route.meta.namespace };
57
+ }
58
+ // 2. Pattern match (dynamic routes: /cars/:id, /blog/:slug/comments/:id, etc.)
59
+ const dynamicRoutes = routeData.filter((r) => typeof r.path === 'string' && r.path.includes(':'));
60
+ const matches = dynamicRoutes.filter((r) => matchRoutePath(r.path, pathname));
61
+ if (matches.length > 0) {
62
+ const best = matches.reduce((a, b) => b.path.length > a.path.length ? b : a);
63
+ if (best.meta) {
64
+ return { ...best.meta, ns: best.meta.namespace };
65
+ }
38
66
  }
39
67
  }
40
- // Extract potential namespace from path
68
+ // Fallback: first path segment as namespace
41
69
  const segments = pathname.split('/').filter(Boolean);
42
70
  if (segments.length > 0) {
43
71
  return { ns: segments[0] };
@@ -64,7 +92,7 @@ const NextJsAutoMetaTags = ({ config = {}, routeMeta: routeMetaOverride, title:
64
92
  const { t } = useTranslation(namespaces);
65
93
  const { defaultNamespace = 'home', defaultImage = '/og-image.png', twitterHandle, defaultAuthor, staticTags = {}, } = config;
66
94
  const siteName = config.siteName || useAppConfig('name');
67
- const baseUrl = useAppConfig('url');
95
+ const baseUrl = getPlatformEnvVar('APP_URL') || '';
68
96
  // Get route metadata
69
97
  const routeMeta = getRouteMetadata(pathname || '/', isClient);
70
98
  const finalRouteMeta = { ...routeMeta, ...routeMetaOverride };
@@ -9,7 +9,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  * @author AMBROISE PARK Consulting
10
10
  */
11
11
  import { ExternalLink } from 'lucide-react';
12
- import { useAppConfig } from '@donotdev/core';
12
+ import { useAppConfig, getPlatformEnvVar } from '@donotdev/core';
13
13
  /**
14
14
  * FooterBranding - Framework branding link (power move)
15
15
  *
@@ -21,7 +21,7 @@ import { useAppConfig } from '@donotdev/core';
21
21
  * @author AMBROISE PARK Consulting
22
22
  */
23
23
  export const FooterBranding = ({ className, }) => {
24
- const appUrl = useAppConfig('url');
24
+ const appUrl = getPlatformEnvVar('APP_URL');
25
25
  const isFrameworkSite = appUrl === 'https://donotdev.com';
26
26
  return (_jsxs("a", { href: isFrameworkSite
27
27
  ? 'https://www.ambroise-park.com'
@@ -4455,6 +4455,167 @@ em {
4455
4455
  padding-block: var(--gap-lg);
4456
4456
  }
4457
4457
 
4458
+ /* packages/components/src/advanced/ImageGallery/ImageGallery.css */
4459
+
4460
+ .image-gallery {
4461
+ display: flex;
4462
+ flex-direction: column;
4463
+ gap: var(--gap-md);
4464
+ outline: none;
4465
+ }
4466
+
4467
+ .image-gallery:focus-visible {
4468
+ outline: 2px solid var(--primary);
4469
+ outline-offset: 2px;
4470
+ border-radius: var(--radius-lg);
4471
+ }
4472
+
4473
+ /* Empty state */
4474
+
4475
+ .image-gallery--empty {
4476
+ display: flex;
4477
+ align-items: center;
4478
+ justify-content: center;
4479
+ background-color: var(--muted);
4480
+ border-radius: var(--radius-lg);
4481
+ }
4482
+
4483
+ .image-gallery__placeholder {
4484
+ color: var(--muted-foreground);
4485
+ font-size: var(--font-size-sm);
4486
+ }
4487
+
4488
+ /* Main image container */
4489
+
4490
+ .image-gallery__main {
4491
+ position: relative;
4492
+ width: 100%;
4493
+ overflow: hidden;
4494
+ border-radius: var(--radius-surface);
4495
+ background-color: var(--muted);
4496
+ }
4497
+
4498
+ .image-gallery__main-image {
4499
+ width: 100%;
4500
+ height: 100%;
4501
+ -o-object-fit: cover;
4502
+ object-fit: cover;
4503
+ display: block;
4504
+ position: relative;
4505
+ }
4506
+
4507
+ /* Navigation arrows */
4508
+
4509
+ .image-gallery__nav {
4510
+ position: absolute;
4511
+ top: 50%;
4512
+ transform: translateY(-50%);
4513
+ display: flex;
4514
+ align-items: center;
4515
+ justify-content: center;
4516
+ width: 44px;
4517
+ height: 44px;
4518
+ border: none;
4519
+ border-radius: var(--radius-full);
4520
+ background-color: var(--background);
4521
+ color: var(--foreground);
4522
+ cursor: pointer;
4523
+ opacity: 0;
4524
+ transition:
4525
+ opacity 0.2s ease,
4526
+ background-color 0.2s ease;
4527
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
4528
+ z-index: 2;
4529
+ }
4530
+
4531
+ .image-gallery__main:hover .image-gallery__nav,
4532
+ .image-gallery:focus-within .image-gallery__nav {
4533
+ opacity: 1;
4534
+ }
4535
+
4536
+ .image-gallery__nav:hover {
4537
+ background-color: var(--primary);
4538
+ color: var(--primary-foreground);
4539
+ }
4540
+
4541
+ .image-gallery__nav:focus-visible {
4542
+ opacity: 1;
4543
+ outline: 2px solid var(--primary);
4544
+ outline-offset: 2px;
4545
+ }
4546
+
4547
+ .image-gallery__nav--prev {
4548
+ inset-inline-start: var(--gap-md);
4549
+ }
4550
+
4551
+ .image-gallery__nav--next {
4552
+ inset-inline-end: var(--gap-md);
4553
+ }
4554
+
4555
+ /* Thumbnails */
4556
+
4557
+ .image-gallery__thumbnails {
4558
+ display: flex;
4559
+ flex-wrap: wrap;
4560
+ gap: var(--gap-sm);
4561
+ }
4562
+
4563
+ .image-gallery__thumbnail {
4564
+ flex: 0 0 auto;
4565
+ width: 80px;
4566
+ height: 60px;
4567
+ padding: 0;
4568
+ border: 2px solid transparent;
4569
+ border-radius: var(--radius-surface);
4570
+ overflow: hidden;
4571
+ cursor: pointer;
4572
+ background: none;
4573
+ transition:
4574
+ border-color 0.2s ease,
4575
+ transform 0.2s ease;
4576
+ }
4577
+
4578
+ .image-gallery__thumbnail:hover {
4579
+ border-color: var(--muted-foreground);
4580
+ }
4581
+
4582
+ .image-gallery__thumbnail:focus-visible {
4583
+ outline: 2px solid var(--primary);
4584
+ outline-offset: 2px;
4585
+ }
4586
+
4587
+ .image-gallery__thumbnail--selected {
4588
+ border-color: var(--primary);
4589
+ }
4590
+
4591
+ .image-gallery__thumbnail-image {
4592
+ width: 100%;
4593
+ height: 100%;
4594
+ -o-object-fit: cover;
4595
+ object-fit: cover;
4596
+ display: block;
4597
+ }
4598
+
4599
+ /* Responsive adjustments */
4600
+
4601
+ @media (max-width: 640px) {
4602
+ .image-gallery__thumbnail {
4603
+ width: 60px;
4604
+ height: 45px;
4605
+ }
4606
+
4607
+ .image-gallery__nav {
4608
+ width: 36px;
4609
+ height: 36px;
4610
+ opacity: 0.8;
4611
+ }
4612
+
4613
+ .image-gallery__nav svg {
4614
+ width: 20px;
4615
+ height: 20px;
4616
+ }
4617
+ }
4618
+
4458
4619
  /* packages/components/src/atomic/Input/Input.css */
4459
4620
 
4460
4621
  /* Hide number input spinners - cleaner UI for price/range inputs */
@@ -7356,6 +7517,24 @@ input[type='number'] {
7356
7517
  font-size: var(--font-size-sm);
7357
7518
  }
7358
7519
 
7520
+ /* Font weight overrides (after level rules, so weight prop overrides level defaults) */
7521
+
7522
+ .dndev-text-base[data-font-weight='normal'] {
7523
+ font-weight: var(--font-weight-normal);
7524
+ }
7525
+
7526
+ .dndev-text-base[data-font-weight='medium'] {
7527
+ font-weight: var(--font-weight-medium);
7528
+ }
7529
+
7530
+ .dndev-text-base[data-font-weight='semibold'] {
7531
+ font-weight: var(--font-weight-semibold);
7532
+ }
7533
+
7534
+ .dndev-text-base[data-font-weight='bold'] {
7535
+ font-weight: var(--font-weight-bold);
7536
+ }
7537
+
7359
7538
  /* packages/components/src/atomic/Toaster/Toaster.css */
7360
7539
 
7361
7540
  .dndev-toast-viewport {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/ui",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -49,22 +49,22 @@
49
49
  "dependencies": {
50
50
  "@hookform/resolvers": "^5.2.2",
51
51
  "react-helmet-async": "^2.0.5",
52
- "react-hook-form": "^7.71.0"
52
+ "react-hook-form": "^7.71.1"
53
53
  },
54
54
  "peerDependencies": {
55
- "@donotdev/adv-comps": "^0.0.8",
55
+ "@donotdev/adv-comps": "^0.0.9",
56
56
  "@donotdev/auth": "^0.0.5",
57
57
  "@donotdev/billing": "^0.0.5",
58
- "@donotdev/components": "^0.0.13",
59
- "@donotdev/core": "^0.0.17",
60
- "@donotdev/crud": "^0.0.8",
61
- "@donotdev/firebase": "^0.0.6",
58
+ "@donotdev/components": "^0.0.15",
59
+ "@donotdev/core": "^0.0.19",
60
+ "@donotdev/crud": "^0.0.10",
61
+ "@donotdev/firebase": "^0.0.8",
62
62
  "@donotdev/oauth": "^0.0.5",
63
- "firebase": "^12.5.0",
64
- "lucide-react": "^0.562.0",
65
- "react": "^19.2.3",
66
- "react-dom": "^19.2.3",
67
- "react-router-dom": "^7.1.3",
63
+ "firebase": "^12.8.0",
64
+ "lucide-react": "^0.563.0",
65
+ "react": "^19.2.4",
66
+ "react-dom": "^19.2.4",
67
+ "react-router-dom": "^7.13.0",
68
68
  "valibot": "^1.2.0"
69
69
  },
70
70
  "peerDependenciesMeta": {
@@ -1,26 +0,0 @@
1
- import type { EntityField, FieldType, ValueTypeForField } from '@donotdev/core';
2
- import type { ReactElement } from 'react';
3
- interface DisplayFieldRendererBaseProps<T extends FieldType = FieldType> {
4
- /** Field identifier */
5
- name: string;
6
- /** Field configuration */
7
- config: EntityField<T>;
8
- /** Translation function */
9
- t: (key: string, options?: Record<string, any>) => string;
10
- /** Field value to display */
11
- value: ValueTypeForField<T>;
12
- /** Additional CSS classes */
13
- className?: string;
14
- }
15
- export type DisplayFieldRendererProps<T extends FieldType> = DisplayFieldRendererBaseProps<T>;
16
- /**
17
- * DisplayFieldRenderer selects and renders the appropriate display component
18
- * based on the field type for read-only display mode.
19
- *
20
- * @version 0.0.1
21
- * @since 0.0.1
22
- * @author AMBROISE PARK Consulting
23
- */
24
- export declare function DisplayFieldRenderer<T extends FieldType>({ name, config, t, value, className, }: DisplayFieldRendererProps<T>): ReactElement;
25
- export default DisplayFieldRenderer;
26
- //# sourceMappingURL=DisplayFieldRenderer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DisplayFieldRenderer.d.ts","sourceRoot":"","sources":["../../../src/crud/components/DisplayFieldRenderer.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AA8BhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,UAAU,6BAA6B,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IACrE,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,2BAA2B;IAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;IAC1D,6BAA6B;IAC7B,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC5B,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAGD,MAAM,MAAM,yBAAyB,CAAC,CAAC,SAAS,SAAS,IACvD,6BAA6B,CAAC,CAAC,CAAC,CAAC;AAEnC;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,SAAS,EAAE,EACxD,IAAI,EACJ,MAAM,EACN,CAAC,EACD,KAAK,EACL,SAAS,GACV,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,YAAY,CAgS7C;AAED,eAAe,oBAAoB,CAAC"}
@@ -1,107 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- // packages/ui/src/crud/components/DisplayFieldRenderer.tsx
3
- /**
4
- * @fileoverview DisplayFieldRenderer component
5
- * @description Renders display fields based on field configuration
6
- *
7
- * @version 0.0.1
8
- * @since 0.0.1
9
- * @author AMBROISE PARK Consulting
10
- */
11
- import { Stack } from '@donotdev/components';
12
- // Import display field components
13
- import { TextFieldDisplay, BadgeFieldDisplay, AvatarFieldDisplay, LinkFieldDisplay, DateFieldDisplay, NumberFieldDisplay, PhoneNumberDisplay, TextAreaDisplay, RichTextDisplay, CheckboxFieldDisplay, DropdownDisplay, MultiDropdownDisplay, MultiInputTextFieldDisplay, RadioFieldDisplay, RangeFieldDisplay, FileFieldDisplay, ImageFieldDisplay, GeoPointFieldDisplay, MapFieldDisplay, ReferenceFieldDisplay, TimestampFieldDisplay, HiddenFieldDisplay, ButtonFieldDisplay, } from './fields/display';
14
- import PasswordFieldDisplay from './fields/display/PasswordFieldDisplay';
15
- /**
16
- * DisplayFieldRenderer selects and renders the appropriate display component
17
- * based on the field type for read-only display mode.
18
- *
19
- * @version 0.0.1
20
- * @since 0.0.1
21
- * @author AMBROISE PARK Consulting
22
- */
23
- export function DisplayFieldRenderer({ name, config, t, value, className, }) {
24
- /**
25
- * Renders appropriate display component based on field type
26
- */
27
- const renderDisplayComponent = () => {
28
- const type = config.type;
29
- switch (type) {
30
- case 'password':
31
- return (_jsx(PasswordFieldDisplay, { config: config, value: value, t: t, className: className, loading: false }));
32
- case 'text':
33
- case 'email':
34
- case 'month':
35
- case 'week':
36
- case 'time':
37
- return (_jsx(TextFieldDisplay, { config: config, value: value, t: t, className: className }));
38
- case 'avatar':
39
- return (_jsx(AvatarFieldDisplay, { config: config, value: value, t: t, className: className }));
40
- case 'badge':
41
- return (_jsx(BadgeFieldDisplay, { config: config, value: value, t: t, className: className }));
42
- case 'boolean':
43
- case 'checkbox':
44
- return (_jsx(CheckboxFieldDisplay, { config: config, value: value, t: t, className: className }));
45
- case 'array':
46
- return (_jsx(MultiInputTextFieldDisplay, { config: config, value: value, t: t, className: className }));
47
- case 'multiselect':
48
- return (_jsx(MultiDropdownDisplay, { config: config, value: value, t: t, className: className }));
49
- case 'image':
50
- return (_jsx(ImageFieldDisplay, { config: config, value: value, t: t, className: className }));
51
- case 'url':
52
- return (_jsx(LinkFieldDisplay, { config: config, value: value, t: t, className: className }));
53
- case 'tel':
54
- return (_jsx(PhoneNumberDisplay, { config: config, value: value, t: t, className: className }));
55
- case 'color':
56
- if (value && typeof value === 'string') {
57
- return (_jsxs(Stack, { direction: "row", align: "center", gap: "tight", children: [_jsx("div", { style: {
58
- backgroundColor: value,
59
- width: '1.5rem',
60
- height: '1.5rem',
61
- }, "aria-label": `Color: ${value}` }), _jsx("span", { style: { fontFamily: 'monospace' }, children: value })] }));
62
- }
63
- return _jsx("span", { style: { color: 'var(--muted-foreground)' }, children: "-" });
64
- case 'number':
65
- case 'range':
66
- return (_jsx(NumberFieldDisplay, { config: config, value: value, t: t, className: className }));
67
- case 'date':
68
- case 'datetime-local':
69
- return (_jsx(DateFieldDisplay, { config: config, value: value, t: t, className: className }));
70
- case 'timestamp':
71
- return (_jsx(TimestampFieldDisplay, { config: config, value: value, t: t, className: className }));
72
- case 'reference':
73
- return (_jsx(ReferenceFieldDisplay, { config: config, value: value, t: t, className: className }));
74
- case 'file':
75
- return (_jsx(FileFieldDisplay, { config: config, value: value, t: t, className: className }));
76
- case 'geopoint':
77
- return (_jsx(GeoPointFieldDisplay, { config: config, value: value, t: t, className: className }));
78
- case 'map':
79
- return (_jsx(MapFieldDisplay, { config: config, value: value, t: t, className: className }));
80
- case 'textarea':
81
- return (_jsx(TextAreaDisplay, { config: config, value: value, t: t, className: className }));
82
- case 'richtext':
83
- return (_jsx(RichTextDisplay, { config: config, value: value, t: t, className: className }));
84
- case 'select':
85
- return (_jsx(DropdownDisplay, { config: config, value: value, t: t, className: className }));
86
- case 'radio':
87
- return (_jsx(RadioFieldDisplay, { config: config, value: value, t: t, className: className }));
88
- case 'hidden':
89
- return (_jsx(HiddenFieldDisplay, { config: config, value: value, t: t, className: className }));
90
- case 'submit':
91
- case 'reset':
92
- return (_jsx(ButtonFieldDisplay, { config: config, value: value, t: t, className: className }));
93
- default:
94
- return (_jsx(TextFieldDisplay, { config: config, value: value, t: t, className: className }));
95
- }
96
- };
97
- // Don't render hidden fields
98
- if (config.visibility === 'hidden') {
99
- return _jsx(_Fragment, {});
100
- }
101
- const displayComponent = renderDisplayComponent();
102
- if (!displayComponent) {
103
- return _jsx(_Fragment, {});
104
- }
105
- return _jsx("div", { className: className, children: displayComponent });
106
- }
107
- export default DisplayFieldRenderer;
@@ -1,23 +0,0 @@
1
- import type { EntityField } from '@donotdev/core';
2
- export interface AvatarFieldDisplayProps {
3
- /** Field configuration */
4
- config: EntityField<'image'>;
5
- /** Value to display (image URL) */
6
- value: string;
7
- /** Translation function */
8
- t: (key: string, options?: Record<string, any>) => string;
9
- /** Additional CSS classes */
10
- className?: string;
11
- /** Avatar size */
12
- size?: 'sm' | 'md' | 'lg';
13
- }
14
- /**
15
- * AvatarFieldDisplay - Displays image values as avatars
16
- *
17
- * @version 0.0.1
18
- * @since 0.0.1
19
- * @author AMBROISE PARK Consulting
20
- */
21
- export declare const AvatarFieldDisplay: React.ComponentType<AvatarFieldDisplayProps>;
22
- export default AvatarFieldDisplay;
23
- //# sourceMappingURL=AvatarFieldDisplay.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AvatarFieldDisplay.d.ts","sourceRoot":"","sources":["../../../../../src/crud/components/fields/display/AvatarFieldDisplay.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,uBAAuB;IACtC,0BAA0B;IAC1B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;IAC1D,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,aAAa,CAClD,uBAAuB,CAiCxB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -1,38 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- // packages/ui/src/crud/components/fields/display/AvatarFieldDisplay.tsx
3
- /**
4
- * @fileoverview AvatarFieldDisplay component
5
- * @description Displays image values as avatars
6
- *
7
- * @version 0.0.1
8
- * @since 0.0.1
9
- * @author AMBROISE PARK Consulting
10
- */
11
- import { Avatar, Text } from '@donotdev/components';
12
- /**
13
- * AvatarFieldDisplay - Displays image values as avatars
14
- *
15
- * @version 0.0.1
16
- * @since 0.0.1
17
- * @author AMBROISE PARK Consulting
18
- */
19
- export const AvatarFieldDisplay = ({ config, value, t, className, size = 'md' }) => {
20
- if (!value) {
21
- return (_jsx(Text, { as: "span", variant: "muted", className: className, children: "-" }));
22
- }
23
- const sizeClasses = {
24
- sm: 'size-touch',
25
- md: 'size-touch',
26
- lg: 'h-16 w-16',
27
- };
28
- const getInitials = (label) => {
29
- return label
30
- .split(' ')
31
- .map((word) => word.charAt(0))
32
- .slice(0, 2)
33
- .join('')
34
- .toUpperCase();
35
- };
36
- return (_jsx(Avatar, { src: value, alt: config.label || 'Avatar', fallback: getInitials(config.label || 'AV'), className: `${sizeClasses[size]} ${className || ''}` }));
37
- };
38
- export default AvatarFieldDisplay;
@@ -1,21 +0,0 @@
1
- import type { EntityField } from '@donotdev/core';
2
- export interface BadgeFieldDisplayProps {
3
- /** Field configuration */
4
- config: EntityField<'boolean' | 'checkbox' | 'select' | 'radio'>;
5
- /** Value to display */
6
- value: boolean | string;
7
- /** Translation function */
8
- t: (key: string, options?: Record<string, any>) => string;
9
- /** Additional CSS classes */
10
- className?: string;
11
- }
12
- /**
13
- * BadgeFieldDisplay - Displays boolean/select values as badges
14
- *
15
- * @version 0.0.1
16
- * @since 0.0.1
17
- * @author AMBROISE PARK Consulting
18
- */
19
- export declare const BadgeFieldDisplay: React.ComponentType<BadgeFieldDisplayProps>;
20
- export default BadgeFieldDisplay;
21
- //# sourceMappingURL=BadgeFieldDisplay.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BadgeFieldDisplay.d.ts","sourceRoot":"","sources":["../../../../../src/crud/components/fields/display/BadgeFieldDisplay.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACrC,0BAA0B;IAC1B,MAAM,EAAE,WAAW,CAAC,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC,CAAC;IACjE,uBAAuB;IACvB,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IACxB,2BAA2B;IAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;IAC1D,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CA6BzE,CAAC;AAEF,eAAe,iBAAiB,CAAC"}