@jant/core 0.3.25 → 0.3.27

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 (133) hide show
  1. package/dist/app.js +70 -563
  2. package/dist/auth.js +3 -0
  3. package/dist/client.js +1 -0
  4. package/dist/i18n/locales/en.js +1 -1
  5. package/dist/i18n/locales/zh-Hans.js +1 -1
  6. package/dist/i18n/locales/zh-Hant.js +1 -1
  7. package/dist/lib/avatar-upload.js +134 -0
  8. package/dist/lib/config.js +39 -0
  9. package/dist/lib/constants.js +10 -10
  10. package/dist/lib/favicon.js +102 -0
  11. package/dist/lib/image.js +13 -17
  12. package/dist/lib/media-helpers.js +2 -2
  13. package/dist/lib/navigation.js +23 -3
  14. package/dist/lib/render.js +10 -1
  15. package/dist/lib/schemas.js +31 -0
  16. package/dist/lib/timezones.js +388 -0
  17. package/dist/lib/view.js +1 -1
  18. package/dist/routes/api/posts.js +1 -1
  19. package/dist/routes/api/upload.js +3 -3
  20. package/dist/routes/auth/reset.js +221 -0
  21. package/dist/routes/auth/setup.js +194 -0
  22. package/dist/routes/auth/signin.js +176 -0
  23. package/dist/routes/dash/collections.js +23 -415
  24. package/dist/routes/dash/media.js +12 -392
  25. package/dist/routes/dash/pages.js +7 -330
  26. package/dist/routes/dash/redirects.js +18 -12
  27. package/dist/routes/dash/settings.js +198 -577
  28. package/dist/routes/feed/rss.js +2 -1
  29. package/dist/routes/feed/sitemap.js +4 -2
  30. package/dist/routes/pages/featured.js +5 -1
  31. package/dist/routes/pages/home.js +26 -1
  32. package/dist/routes/pages/latest.js +45 -0
  33. package/dist/services/post.js +30 -50
  34. package/dist/types/bindings.js +3 -0
  35. package/dist/types/config.js +147 -0
  36. package/dist/types/constants.js +27 -0
  37. package/dist/types/entities.js +3 -0
  38. package/dist/types/operations.js +3 -0
  39. package/dist/types/props.js +3 -0
  40. package/dist/types/views.js +5 -0
  41. package/dist/types.js +8 -111
  42. package/dist/ui/color-themes.js +33 -33
  43. package/dist/ui/compose/ComposeDialog.js +36 -21
  44. package/dist/ui/dash/PageForm.js +21 -15
  45. package/dist/ui/dash/PostForm.js +22 -16
  46. package/dist/ui/dash/collections/CollectionForm.js +152 -0
  47. package/dist/ui/dash/collections/CollectionsListContent.js +68 -0
  48. package/dist/ui/dash/collections/ViewCollectionContent.js +96 -0
  49. package/dist/ui/dash/media/MediaListContent.js +166 -0
  50. package/dist/ui/dash/media/ViewMediaContent.js +212 -0
  51. package/dist/ui/dash/pages/LinkFormContent.js +130 -0
  52. package/dist/ui/dash/pages/UnifiedPagesContent.js +193 -0
  53. package/dist/ui/dash/settings/AccountContent.js +209 -0
  54. package/dist/ui/dash/settings/AppearanceContent.js +259 -0
  55. package/dist/ui/dash/settings/GeneralContent.js +536 -0
  56. package/dist/ui/dash/settings/SettingsNav.js +41 -0
  57. package/dist/ui/font-themes.js +36 -0
  58. package/dist/ui/layouts/BaseLayout.js +24 -2
  59. package/dist/ui/layouts/SiteLayout.js +47 -19
  60. package/package.json +1 -1
  61. package/src/app.tsx +95 -553
  62. package/src/auth.ts +4 -1
  63. package/src/client.ts +1 -0
  64. package/src/i18n/locales/en.po +240 -175
  65. package/src/i18n/locales/en.ts +1 -1
  66. package/src/i18n/locales/zh-Hans.po +240 -175
  67. package/src/i18n/locales/zh-Hans.ts +1 -1
  68. package/src/i18n/locales/zh-Hant.po +240 -175
  69. package/src/i18n/locales/zh-Hant.ts +1 -1
  70. package/src/lib/__tests__/config.test.ts +192 -0
  71. package/src/lib/__tests__/favicon.test.ts +151 -0
  72. package/src/lib/__tests__/image.test.ts +2 -6
  73. package/src/lib/__tests__/timezones.test.ts +61 -0
  74. package/src/lib/__tests__/view.test.ts +2 -2
  75. package/src/lib/avatar-upload.ts +165 -0
  76. package/src/lib/config.ts +47 -0
  77. package/src/lib/constants.ts +19 -11
  78. package/src/lib/favicon.ts +115 -0
  79. package/src/lib/image.ts +13 -21
  80. package/src/lib/media-helpers.ts +2 -2
  81. package/src/lib/navigation.ts +33 -2
  82. package/src/lib/render.tsx +15 -1
  83. package/src/lib/schemas.ts +39 -0
  84. package/src/lib/timezones.ts +325 -0
  85. package/src/lib/view.ts +1 -1
  86. package/src/routes/api/posts.ts +1 -1
  87. package/src/routes/api/upload.ts +2 -3
  88. package/src/routes/auth/reset.tsx +239 -0
  89. package/src/routes/auth/setup.tsx +189 -0
  90. package/src/routes/auth/signin.tsx +163 -0
  91. package/src/routes/dash/__tests__/settings-avatar.test.ts +89 -0
  92. package/src/routes/dash/collections.tsx +17 -366
  93. package/src/routes/dash/media.tsx +12 -414
  94. package/src/routes/dash/pages.tsx +8 -348
  95. package/src/routes/dash/redirects.tsx +20 -14
  96. package/src/routes/dash/settings.tsx +243 -534
  97. package/src/routes/feed/__tests__/rss.test.ts +141 -0
  98. package/src/routes/feed/rss.ts +3 -1
  99. package/src/routes/feed/sitemap.ts +4 -2
  100. package/src/routes/pages/featured.tsx +7 -1
  101. package/src/routes/pages/home.tsx +25 -2
  102. package/src/routes/pages/latest.tsx +59 -0
  103. package/src/services/post.ts +34 -66
  104. package/src/styles/components.css +0 -65
  105. package/src/styles/tokens.css +1 -1
  106. package/src/styles/ui.css +24 -40
  107. package/src/types/bindings.ts +30 -0
  108. package/src/types/config.ts +183 -0
  109. package/src/types/constants.ts +26 -0
  110. package/src/types/entities.ts +109 -0
  111. package/src/types/operations.ts +88 -0
  112. package/src/types/props.ts +115 -0
  113. package/src/types/views.ts +172 -0
  114. package/src/types.ts +8 -644
  115. package/src/ui/__tests__/font-themes.test.ts +34 -0
  116. package/src/ui/color-themes.ts +34 -34
  117. package/src/ui/compose/ComposeDialog.tsx +40 -21
  118. package/src/ui/dash/PageForm.tsx +25 -19
  119. package/src/ui/dash/PostForm.tsx +26 -20
  120. package/src/ui/dash/collections/CollectionForm.tsx +153 -0
  121. package/src/ui/dash/collections/CollectionsListContent.tsx +85 -0
  122. package/src/ui/dash/collections/ViewCollectionContent.tsx +92 -0
  123. package/src/ui/dash/media/MediaListContent.tsx +201 -0
  124. package/src/ui/dash/media/ViewMediaContent.tsx +208 -0
  125. package/src/ui/dash/pages/LinkFormContent.tsx +119 -0
  126. package/src/ui/dash/pages/UnifiedPagesContent.tsx +203 -0
  127. package/src/ui/dash/settings/AccountContent.tsx +176 -0
  128. package/src/ui/dash/settings/AppearanceContent.tsx +254 -0
  129. package/src/ui/dash/settings/GeneralContent.tsx +533 -0
  130. package/src/ui/dash/settings/SettingsNav.tsx +56 -0
  131. package/src/ui/font-themes.ts +54 -0
  132. package/src/ui/layouts/BaseLayout.tsx +17 -0
  133. package/src/ui/layouts/SiteLayout.tsx +45 -31
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Media grid list with upload UI
3
+ */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
4
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
5
+ import { EmptyState } from "../index.js";
6
+ import { getMediaUrl, getImageUrl, getPublicUrlForProvider } from "../../../lib/image.js";
7
+ function formatSize(bytes) {
8
+ if (bytes < 1024) return `${bytes} B`;
9
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
10
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
11
+ }
12
+ function MediaCard({ media, r2PublicUrl, imageTransformUrl, s3PublicUrl }) {
13
+ const publicUrl = getPublicUrlForProvider(media.provider, r2PublicUrl, s3PublicUrl);
14
+ const fullUrl = getMediaUrl(media.storageKey, publicUrl);
15
+ const thumbnailUrl = getImageUrl(fullUrl, imageTransformUrl, {
16
+ width: 300,
17
+ quality: 80,
18
+ format: "auto",
19
+ fit: "cover"
20
+ });
21
+ const isImage = media.mimeType.startsWith("image/");
22
+ return /*#__PURE__*/ _jsxs("div", {
23
+ class: "group relative",
24
+ "data-media-id": media.id,
25
+ children: [
26
+ isImage ? /*#__PURE__*/ _jsx("button", {
27
+ type: "button",
28
+ class: "block w-full aspect-square bg-muted rounded-lg overflow-hidden border hover:border-primary cursor-pointer",
29
+ onclick: `document.getElementById('lightbox-img').src = '${fullUrl}'; document.getElementById('lightbox').showModal()`,
30
+ children: /*#__PURE__*/ _jsx("img", {
31
+ src: thumbnailUrl,
32
+ alt: media.alt || media.originalName,
33
+ class: "w-full h-full object-cover",
34
+ loading: "lazy"
35
+ })
36
+ }) : /*#__PURE__*/ _jsx("a", {
37
+ href: `/dash/media/${media.id}`,
38
+ class: "block aspect-square bg-muted rounded-lg overflow-hidden border hover:border-primary",
39
+ children: /*#__PURE__*/ _jsx("div", {
40
+ class: "w-full h-full flex items-center justify-center text-muted-foreground",
41
+ children: /*#__PURE__*/ _jsx("span", {
42
+ class: "text-xs",
43
+ children: media.mimeType
44
+ })
45
+ })
46
+ }),
47
+ /*#__PURE__*/ _jsx("a", {
48
+ href: `/dash/media/${media.id}`,
49
+ class: "block mt-2 text-xs truncate hover:underline",
50
+ title: media.originalName,
51
+ children: media.originalName
52
+ }),
53
+ /*#__PURE__*/ _jsx("div", {
54
+ class: "text-xs text-muted-foreground",
55
+ children: formatSize(media.size)
56
+ })
57
+ ]
58
+ });
59
+ }
60
+ export function MediaListContent({ mediaList, r2PublicUrl, imageTransformUrl, s3PublicUrl }) {
61
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
62
+ const processingText = $__i18n._({
63
+ id: "k1ifdL",
64
+ message: "Processing..."
65
+ });
66
+ const uploadingText = $__i18n._({
67
+ id: "GxkJXS",
68
+ message: "Uploading..."
69
+ });
70
+ const uploadText = $__i18n._({
71
+ id: "ONWvwQ",
72
+ message: "Upload"
73
+ });
74
+ const errorText = $__i18n._({
75
+ id: "pZq3aX",
76
+ message: "Upload failed. Please try again."
77
+ });
78
+ return /*#__PURE__*/ _jsxs(_Fragment, {
79
+ children: [
80
+ /*#__PURE__*/ _jsx("form", {
81
+ id: "upload-form",
82
+ class: "hidden",
83
+ enctype: "multipart/form-data",
84
+ "data-on:submit__prevent": "@post('/api/upload', {contentType: 'form'})",
85
+ children: /*#__PURE__*/ _jsx("input", {
86
+ id: "upload-file-input",
87
+ type: "file",
88
+ name: "file"
89
+ })
90
+ }),
91
+ /*#__PURE__*/ _jsxs("div", {
92
+ class: "flex items-center justify-between mb-6",
93
+ children: [
94
+ /*#__PURE__*/ _jsx("h1", {
95
+ class: "text-2xl font-semibold",
96
+ children: $__i18n._({
97
+ id: "xYilR2",
98
+ message: "Media"
99
+ })
100
+ }),
101
+ /*#__PURE__*/ _jsxs("label", {
102
+ class: "btn cursor-pointer",
103
+ children: [
104
+ /*#__PURE__*/ _jsx("span", {
105
+ children: uploadText
106
+ }),
107
+ /*#__PURE__*/ _jsx("input", {
108
+ type: "file",
109
+ class: "hidden",
110
+ accept: "image/*",
111
+ "data-media-upload": true,
112
+ "data-text-processing": processingText,
113
+ "data-text-uploading": uploadingText,
114
+ "data-text-error": errorText
115
+ })
116
+ ]
117
+ })
118
+ ]
119
+ }),
120
+ /*#__PURE__*/ _jsx("div", {
121
+ class: "card mb-6",
122
+ children: /*#__PURE__*/ _jsx("section", {
123
+ class: "text-sm text-muted-foreground",
124
+ children: /*#__PURE__*/ _jsx("p", {
125
+ children: $__i18n._({
126
+ id: "x+doid",
127
+ message: "Images are automatically optimized: resized to max 1920px, converted to WebP, and metadata stripped."
128
+ })
129
+ })
130
+ })
131
+ }),
132
+ /*#__PURE__*/ _jsx("div", {
133
+ id: "media-content",
134
+ children: mediaList.length === 0 ? /*#__PURE__*/ _jsx("div", {
135
+ id: "empty-state",
136
+ children: /*#__PURE__*/ _jsx(EmptyState, {
137
+ message: $__i18n._({
138
+ id: "ST+lN2",
139
+ message: "No media uploaded yet."
140
+ })
141
+ })
142
+ }) : /*#__PURE__*/ _jsx("div", {
143
+ id: "media-grid",
144
+ class: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4",
145
+ children: mediaList.map((m)=>/*#__PURE__*/ _jsx(MediaCard, {
146
+ media: m,
147
+ r2PublicUrl: r2PublicUrl,
148
+ imageTransformUrl: imageTransformUrl,
149
+ s3PublicUrl: s3PublicUrl
150
+ }, m.id))
151
+ })
152
+ }),
153
+ /*#__PURE__*/ _jsx("dialog", {
154
+ id: "lightbox",
155
+ class: "p-0 m-auto bg-transparent backdrop:bg-black/80",
156
+ onclick: "event.target === this && this.close()",
157
+ children: /*#__PURE__*/ _jsx("img", {
158
+ id: "lightbox-img",
159
+ src: "",
160
+ alt: "",
161
+ class: "max-w-[90vw] max-h-[90vh] object-contain rounded-lg"
162
+ })
163
+ })
164
+ ]
165
+ });
166
+ }
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Single media detail view
3
+ */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
4
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
5
+ import { DangerZone } from "../index.js";
6
+ import * as time from "../../../lib/time.js";
7
+ import { getMediaUrl, getImageUrl, getPublicUrlForProvider } from "../../../lib/image.js";
8
+ function formatSize(bytes) {
9
+ if (bytes < 1024) return `${bytes} B`;
10
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
11
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
12
+ }
13
+ export function ViewMediaContent({ media, r2PublicUrl, imageTransformUrl, s3PublicUrl }) {
14
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
15
+ const publicUrl = getPublicUrlForProvider(media.provider, r2PublicUrl, s3PublicUrl);
16
+ const url = getMediaUrl(media.storageKey, publicUrl);
17
+ const thumbnailUrl = getImageUrl(url, imageTransformUrl, {
18
+ width: 600,
19
+ quality: 85,
20
+ format: "auto"
21
+ });
22
+ const isImage = media.mimeType.startsWith("image/");
23
+ return /*#__PURE__*/ _jsxs(_Fragment, {
24
+ children: [
25
+ /*#__PURE__*/ _jsxs("div", {
26
+ class: "flex items-center justify-between mb-6",
27
+ children: [
28
+ /*#__PURE__*/ _jsxs("div", {
29
+ children: [
30
+ /*#__PURE__*/ _jsx("h1", {
31
+ class: "text-2xl font-semibold",
32
+ children: media.originalName
33
+ }),
34
+ /*#__PURE__*/ _jsxs("p", {
35
+ class: "text-muted-foreground mt-1",
36
+ children: [
37
+ formatSize(media.size),
38
+ " · ",
39
+ media.mimeType,
40
+ " ·",
41
+ " ",
42
+ time.formatDate(media.createdAt)
43
+ ]
44
+ })
45
+ ]
46
+ }),
47
+ /*#__PURE__*/ _jsx("a", {
48
+ href: "/dash/media",
49
+ class: "btn-outline",
50
+ children: $__i18n._({
51
+ id: "iH8pgl",
52
+ message: "Back"
53
+ })
54
+ })
55
+ ]
56
+ }),
57
+ /*#__PURE__*/ _jsxs("div", {
58
+ class: "grid gap-6 md:grid-cols-2",
59
+ children: [
60
+ /*#__PURE__*/ _jsxs("div", {
61
+ class: "card",
62
+ children: [
63
+ /*#__PURE__*/ _jsx("header", {
64
+ children: /*#__PURE__*/ _jsx("h2", {
65
+ children: $__i18n._({
66
+ id: "rdUucN",
67
+ message: "Preview"
68
+ })
69
+ })
70
+ }),
71
+ /*#__PURE__*/ _jsx("section", {
72
+ children: isImage ? /*#__PURE__*/ _jsxs(_Fragment, {
73
+ children: [
74
+ /*#__PURE__*/ _jsx("button", {
75
+ type: "button",
76
+ class: "cursor-pointer",
77
+ onclick: `document.getElementById('lightbox-img').src = '${url}'; document.getElementById('lightbox').showModal()`,
78
+ children: /*#__PURE__*/ _jsx("img", {
79
+ src: thumbnailUrl,
80
+ alt: media.alt || media.originalName,
81
+ class: "max-w-full rounded-lg hover:opacity-90 transition-opacity"
82
+ })
83
+ }),
84
+ /*#__PURE__*/ _jsx("p", {
85
+ class: "text-xs text-muted-foreground mt-2",
86
+ children: $__i18n._({
87
+ id: "M1RvTd",
88
+ message: "Click image to view full size"
89
+ })
90
+ })
91
+ ]
92
+ }) : /*#__PURE__*/ _jsx("div", {
93
+ class: "aspect-video bg-muted rounded-lg flex items-center justify-center text-muted-foreground",
94
+ children: /*#__PURE__*/ _jsx("span", {
95
+ children: media.mimeType
96
+ })
97
+ })
98
+ })
99
+ ]
100
+ }),
101
+ /*#__PURE__*/ _jsxs("div", {
102
+ class: "space-y-6",
103
+ children: [
104
+ /*#__PURE__*/ _jsxs("div", {
105
+ class: "card",
106
+ children: [
107
+ /*#__PURE__*/ _jsx("header", {
108
+ children: /*#__PURE__*/ _jsx("h2", {
109
+ children: $__i18n._({
110
+ id: "IagCbF",
111
+ message: "URL"
112
+ })
113
+ })
114
+ }),
115
+ /*#__PURE__*/ _jsxs("section", {
116
+ children: [
117
+ /*#__PURE__*/ _jsxs("div", {
118
+ class: "flex items-center gap-2",
119
+ children: [
120
+ /*#__PURE__*/ _jsx("input", {
121
+ type: "text",
122
+ class: "input flex-1 font-mono text-sm",
123
+ value: url,
124
+ readonly: true
125
+ }),
126
+ /*#__PURE__*/ _jsx("button", {
127
+ type: "button",
128
+ class: "btn-outline",
129
+ onclick: `navigator.clipboard.writeText('${url}')`,
130
+ children: $__i18n._({
131
+ id: "he3ygx",
132
+ message: "Copy"
133
+ })
134
+ })
135
+ ]
136
+ }),
137
+ /*#__PURE__*/ _jsx("p", {
138
+ class: "text-xs text-muted-foreground mt-2",
139
+ children: $__i18n._({
140
+ id: "K9NcLu",
141
+ message: "Use this URL to embed the media in your posts."
142
+ })
143
+ })
144
+ ]
145
+ })
146
+ ]
147
+ }),
148
+ /*#__PURE__*/ _jsxs("div", {
149
+ class: "card",
150
+ children: [
151
+ /*#__PURE__*/ _jsx("header", {
152
+ children: /*#__PURE__*/ _jsx("h2", {
153
+ children: $__i18n._({
154
+ id: "u6Hp4N",
155
+ message: "Markdown"
156
+ })
157
+ })
158
+ }),
159
+ /*#__PURE__*/ _jsx("section", {
160
+ children: /*#__PURE__*/ _jsxs("div", {
161
+ class: "flex items-center gap-2",
162
+ children: [
163
+ /*#__PURE__*/ _jsx("input", {
164
+ type: "text",
165
+ class: "input flex-1 font-mono text-sm",
166
+ value: `![${media.alt || media.originalName}](${url})`,
167
+ readonly: true
168
+ }),
169
+ /*#__PURE__*/ _jsx("button", {
170
+ type: "button",
171
+ class: "btn-outline",
172
+ onclick: `navigator.clipboard.writeText('![${media.alt || media.originalName}](${url})')`,
173
+ children: $__i18n._({
174
+ id: "he3ygx",
175
+ message: "Copy"
176
+ })
177
+ })
178
+ ]
179
+ })
180
+ })
181
+ ]
182
+ }),
183
+ /*#__PURE__*/ _jsx(DangerZone, {
184
+ actionLabel: $__i18n._({
185
+ id: "wM5UXj",
186
+ message: "Delete Media"
187
+ }),
188
+ formAction: `/dash/media/${media.id}/delete`,
189
+ confirmMessage: "Are you sure you want to delete this media?",
190
+ description: $__i18n._({
191
+ id: "E80cJw",
192
+ message: "Deleting this media will remove it permanently from storage."
193
+ })
194
+ })
195
+ ]
196
+ })
197
+ ]
198
+ }),
199
+ isImage && /*#__PURE__*/ _jsx("dialog", {
200
+ id: "lightbox",
201
+ class: "p-0 m-auto bg-transparent backdrop:bg-black/80",
202
+ onclick: "event.target === this && this.close()",
203
+ children: /*#__PURE__*/ _jsx("img", {
204
+ id: "lightbox-img",
205
+ src: "",
206
+ alt: "",
207
+ class: "max-w-[90vw] max-h-[90vh] object-contain rounded-lg"
208
+ })
209
+ })
210
+ ]
211
+ });
212
+ }
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Link creation/editing form
3
+ */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
4
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
5
+ export function LinkFormContent({ item, isEdit }) {
6
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
7
+ const title = isEdit ? $__i18n._({
8
+ id: "gDx5MG",
9
+ message: "Edit Link"
10
+ }) : $__i18n._({
11
+ id: "aaGV/9",
12
+ message: "New Link"
13
+ });
14
+ const signals = JSON.stringify({
15
+ label: item?.label ?? "",
16
+ url: item?.url ?? ""
17
+ }).replace(/</g, "\\u003c");
18
+ const action = isEdit ? `/dash/pages/links/${item?.id}` : "/dash/pages/links";
19
+ return /*#__PURE__*/ _jsxs(_Fragment, {
20
+ children: [
21
+ /*#__PURE__*/ _jsx("h1", {
22
+ class: "text-2xl font-semibold mb-6",
23
+ children: title
24
+ }),
25
+ /*#__PURE__*/ _jsxs("form", {
26
+ "data-signals": signals,
27
+ "data-on:submit__prevent": `@post('${action}')`,
28
+ "data-indicator": "_loading",
29
+ class: "flex flex-col gap-4 max-w-lg",
30
+ children: [
31
+ /*#__PURE__*/ _jsxs("div", {
32
+ class: "field",
33
+ children: [
34
+ /*#__PURE__*/ _jsx("label", {
35
+ class: "label",
36
+ children: $__i18n._({
37
+ id: "87a/t/",
38
+ message: "Label"
39
+ })
40
+ }),
41
+ /*#__PURE__*/ _jsx("input", {
42
+ type: "text",
43
+ "data-bind": "label",
44
+ class: "input",
45
+ placeholder: "Home",
46
+ required: true
47
+ }),
48
+ /*#__PURE__*/ _jsx("p", {
49
+ class: "text-xs text-muted-foreground mt-1",
50
+ children: $__i18n._({
51
+ id: "+bHzpy",
52
+ message: "Display text for the link"
53
+ })
54
+ })
55
+ ]
56
+ }),
57
+ /*#__PURE__*/ _jsxs("div", {
58
+ class: "field",
59
+ children: [
60
+ /*#__PURE__*/ _jsx("label", {
61
+ class: "label",
62
+ children: $__i18n._({
63
+ id: "IagCbF",
64
+ message: "URL"
65
+ })
66
+ }),
67
+ /*#__PURE__*/ _jsx("input", {
68
+ type: "text",
69
+ "data-bind": "url",
70
+ class: "input",
71
+ placeholder: "/archive or https://...",
72
+ required: true
73
+ }),
74
+ /*#__PURE__*/ _jsx("p", {
75
+ class: "text-xs text-muted-foreground mt-1",
76
+ children: $__i18n._({
77
+ id: "QEbNBb",
78
+ message: "Path (e.g. /archive) or full URL (e.g. https://example.com)"
79
+ })
80
+ })
81
+ ]
82
+ }),
83
+ /*#__PURE__*/ _jsxs("div", {
84
+ class: "flex gap-2",
85
+ children: [
86
+ /*#__PURE__*/ _jsxs("button", {
87
+ type: "submit",
88
+ class: "btn",
89
+ "data-attr:disabled": "$_loading",
90
+ children: [
91
+ /*#__PURE__*/ _jsx("svg", {
92
+ "data-show": "$_loading",
93
+ style: "display:none",
94
+ class: "animate-spin size-4",
95
+ xmlns: "http://www.w3.org/2000/svg",
96
+ viewBox: "0 0 24 24",
97
+ fill: "none",
98
+ stroke: "currentColor",
99
+ "stroke-width": "2",
100
+ "stroke-linecap": "round",
101
+ "stroke-linejoin": "round",
102
+ role: "status",
103
+ children: /*#__PURE__*/ _jsx("path", {
104
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
105
+ })
106
+ }),
107
+ isEdit ? $__i18n._({
108
+ id: "IUwGEM",
109
+ message: "Save Changes"
110
+ }) : $__i18n._({
111
+ id: "kd7eBB",
112
+ message: "Create Link"
113
+ })
114
+ ]
115
+ }),
116
+ /*#__PURE__*/ _jsx("a", {
117
+ href: "/dash/pages",
118
+ class: "btn-outline",
119
+ children: $__i18n._({
120
+ id: "dEgA5A",
121
+ message: "Cancel"
122
+ })
123
+ })
124
+ ]
125
+ })
126
+ ]
127
+ })
128
+ ]
129
+ });
130
+ }