@loykin/designkit 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,11 +8,19 @@ Do not generate an application workflow from a template name alone. DesignKit
8
8
  ships versioned implementation guides that connect routes, query boundaries,
9
9
  loading behavior, action placement, and the correct page templates.
10
10
 
11
- | Product workflow | Guide ID | Connected destinations |
12
- | ------------------- | --------------------- | -------------------------------------- |
13
- | Administrative CRUD | `managed-table` | table → detail Sheet; create/edit page |
14
- | Publishing | `publishing-workflow` | blog collectionarticle route |
15
- | Commerce | `commerce-workflow` | filtered catalog product route |
11
+ | Product workflow | Guide ID | Connected destinations |
12
+ | ------------------- | ---------------------- | -------------------------------------- |
13
+ | Administrative CRUD | `managed-table` | table → detail Sheet; create/edit page |
14
+ | Operations | `kubernetes-workspace` | Pod tabledetail panel → tool dock |
15
+ | Forms | `form-workflow` | create, edit, and settings pages |
16
+ | Publishing | `publishing-workflow` | blog collection → article route |
17
+ | Commerce | `commerce-workflow` | filtered catalog → product route |
18
+
19
+ The executable **Forms / Stacked Form** Playground guide uses React Hook Form
20
+ to demonstrate shared state, controlled DesignKit inputs, validation, and
21
+ modular section components. React Hook Form is installed in the Playground
22
+ only; it is not a dependency or peer dependency of `@loykin/designkit` and is
23
+ not required to preserve the form design contract.
16
24
 
17
25
  List the guides included with the installed package:
18
26
 
@@ -24,6 +32,8 @@ Print a complete contract for a developer or coding agent:
24
32
 
25
33
  ```bash
26
34
  npx @loykin/designkit guide managed-table
35
+ npx @loykin/designkit guide kubernetes-workspace --prompt
36
+ npx @loykin/designkit guide form-workflow --prompt
27
37
  npx @loykin/designkit guide publishing-workflow --prompt
28
38
  npx @loykin/designkit guide commerce-workflow
29
39
  ```
package/cli/designkit.mjs CHANGED
@@ -70,9 +70,17 @@ if (!command || command === 'help' || command === '--help' || command === '-h')
70
70
  )
71
71
  } else {
72
72
  const contract = await readFile(join(guideRoot, guide.contract), 'utf8')
73
- const prompt = wantsPrompt
74
- ? `Implement this workflow with @loykin/designkit ${packageJson.version}. Follow the complete contract below. Preserve route, query, action-placement, loading, and page-template boundaries. Do not nest page-level templates.\n\n`
75
- : ''
76
- process.stdout.write(`${prompt}${contract.trim()}\n`)
73
+ if (!wantsPrompt) {
74
+ process.stdout.write(`${contract.trim()}\n`)
75
+ } else {
76
+ const uiContract = await readFile(
77
+ join(guideRoot, 'ai-ui-implementation-contract.md'),
78
+ 'utf8',
79
+ )
80
+ const prompt = `Implement this workflow with @loykin/designkit ${packageJson.version}. Follow the complete contract below. Preserve route, query, action-placement, loading, and page-template boundaries. Do not nest page-level templates.\n\n`
81
+ process.stdout.write(
82
+ `${prompt}${uiContract.trim()}\n\n---\n\n${contract.trim()}\n`,
83
+ )
84
+ }
77
85
  }
78
86
  }
package/dist/index.cjs CHANGED
@@ -2495,7 +2495,7 @@ function ResizeHandle({
2495
2495
  }
2496
2496
  );
2497
2497
  }
2498
- function WorkbenchBodyTemplate({
2498
+ function WorkbenchBodyTemplateRoot({
2499
2499
  theme,
2500
2500
  className,
2501
2501
  contentClassName,
@@ -2786,6 +2786,21 @@ function WorkbenchBodyTemplate({
2786
2786
  ] })
2787
2787
  ] });
2788
2788
  }
2789
+ function WorkbenchSection({ title, description, actions, className, children }) {
2790
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: cn("space-y-2.5 p-3", className), children: [
2791
+ (title || description || actions) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
2792
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
2793
+ title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: title }),
2794
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description })
2795
+ ] }),
2796
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: actions })
2797
+ ] }),
2798
+ children
2799
+ ] });
2800
+ }
2801
+ var WorkbenchBodyTemplate = Object.assign(WorkbenchBodyTemplateRoot, {
2802
+ Section: WorkbenchSection
2803
+ });
2789
2804
  var DataBodyTemplateContext = React2__namespace.default.createContext(false);
2790
2805
  function useDataBodyTemplateParent(component) {
2791
2806
  if (!React2__namespace.default.useContext(DataBodyTemplateContext)) {
@@ -3524,52 +3539,6 @@ function ListDetailBodyTemplate({
3524
3539
  }
3525
3540
  );
3526
3541
  }
3527
- function PanelTemplateSection({
3528
- title,
3529
- description,
3530
- actions,
3531
- className,
3532
- children
3533
- }) {
3534
- return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: cn("space-y-2.5", className), children: [
3535
- (title || description || actions) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
3536
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
3537
- title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: title }),
3538
- description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description })
3539
- ] }),
3540
- actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: actions })
3541
- ] }),
3542
- children
3543
- ] });
3544
- }
3545
- function PanelTemplateRoot({
3546
- title,
3547
- eyebrow,
3548
- status,
3549
- actions,
3550
- footer,
3551
- children,
3552
- className,
3553
- bodyClassName
3554
- }) {
3555
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-full flex-col overflow-hidden", className), children: [
3556
- (title || eyebrow || actions) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 px-4 py-3", children: [
3557
- eyebrow && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-0.5 text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: eyebrow }),
3558
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3559
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
3560
- title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "min-w-0 truncate text-sm font-semibold", children: title }),
3561
- status && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: status })
3562
- ] }),
3563
- actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-1", children: actions })
3564
- ] })
3565
- ] }),
3566
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("min-h-0 flex-1 overflow-y-auto px-4 py-4", bodyClassName), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-5", children }) }),
3567
- footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-t border-border px-4 py-3", children: footer })
3568
- ] });
3569
- }
3570
- var PanelTemplate = Object.assign(PanelTemplateRoot, {
3571
- Section: PanelTemplateSection
3572
- });
3573
3542
  function FormWizardBodyTemplate({
3574
3543
  theme,
3575
3544
  title,
@@ -4120,6 +4089,196 @@ function PageTopBar({
4120
4089
  }
4121
4090
  );
4122
4091
  }
4092
+ function PanelTemplateSection({
4093
+ title,
4094
+ description,
4095
+ actions,
4096
+ className,
4097
+ children
4098
+ }) {
4099
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: cn("space-y-2.5", className), children: [
4100
+ (title || description || actions) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
4101
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
4102
+ title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: title }),
4103
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description })
4104
+ ] }),
4105
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: actions })
4106
+ ] }),
4107
+ children
4108
+ ] });
4109
+ }
4110
+ function PanelTemplateRow({ label, children, className }) {
4111
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid grid-cols-[6rem_minmax(0,1fr)] gap-3", className), children: [
4112
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-xs text-muted-foreground", children: label }),
4113
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "min-w-0 break-words font-mono text-xs", children })
4114
+ ] });
4115
+ }
4116
+ function PanelTemplateRoot({
4117
+ title,
4118
+ eyebrow,
4119
+ status,
4120
+ actions,
4121
+ footer,
4122
+ children,
4123
+ className,
4124
+ bodyClassName
4125
+ }) {
4126
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-full flex-col overflow-hidden", className), children: [
4127
+ (title || eyebrow || actions) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 px-4 py-3", children: [
4128
+ eyebrow && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-0.5 text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: eyebrow }),
4129
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4130
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
4131
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "min-w-0 truncate text-sm font-semibold", children: title }),
4132
+ status && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: status })
4133
+ ] }),
4134
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-1", children: actions })
4135
+ ] })
4136
+ ] }),
4137
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("min-h-0 flex-1 overflow-y-auto px-4 py-4", bodyClassName), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-5", children }) }),
4138
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-t border-border px-4 py-3", children: footer })
4139
+ ] });
4140
+ }
4141
+ var PanelTemplate = Object.assign(PanelTemplateRoot, {
4142
+ Section: PanelTemplateSection,
4143
+ Row: PanelTemplateRow
4144
+ });
4145
+ function InteractiveCard({ className, ...props }) {
4146
+ return /* @__PURE__ */ jsxRuntime.jsx(
4147
+ Card,
4148
+ {
4149
+ className: cn(
4150
+ "group h-full cursor-pointer gap-0 overflow-hidden py-0 transition-all hover:-translate-y-0.5 hover:shadow-md",
4151
+ className
4152
+ ),
4153
+ ...props
4154
+ }
4155
+ );
4156
+ }
4157
+ var articleToneGradients = {
4158
+ violet: "from-violet-500/80 via-indigo-500/70 to-sky-500/70",
4159
+ emerald: "from-emerald-500/80 via-teal-500/70 to-cyan-500/70",
4160
+ amber: "from-amber-500/80 via-orange-500/70 to-rose-500/70",
4161
+ rose: "from-rose-500/80 via-pink-500/70 to-fuchsia-500/70",
4162
+ sky: "from-sky-500/80 via-blue-500/70 to-indigo-500/70",
4163
+ slate: "from-slate-500/80 via-slate-600/70 to-slate-700/70"
4164
+ };
4165
+ function ArticleCover({ tone, className, children }) {
4166
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative bg-gradient-to-br", articleToneGradients[tone], className), children });
4167
+ }
4168
+ function ArticleByline({
4169
+ author,
4170
+ initials,
4171
+ meta,
4172
+ size = "default",
4173
+ className
4174
+ }) {
4175
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center", size === "sm" ? "gap-2" : "gap-3", className), children: [
4176
+ /* @__PURE__ */ jsxRuntime.jsx(Avatar, { size: size === "sm" ? "sm" : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: initials }) }),
4177
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
4178
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("truncate font-medium", size === "sm" ? "text-xs" : "text-sm"), children: author }),
4179
+ meta && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: meta })
4180
+ ] })
4181
+ ] });
4182
+ }
4183
+ function ArticleToc({ title = "On this page", items, className }) {
4184
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-3", className), children: [
4185
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: title }),
4186
+ items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
4187
+ "a",
4188
+ {
4189
+ href: item.href,
4190
+ className: cn(
4191
+ "block text-sm",
4192
+ item.emphasis ? "font-medium" : "text-muted-foreground"
4193
+ ),
4194
+ children: item.label
4195
+ },
4196
+ item.href
4197
+ ))
4198
+ ] });
4199
+ }
4200
+ function ArticleBody({ className, children }) {
4201
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mx-auto max-w-3xl space-y-6 text-[15px] leading-7", className), children });
4202
+ }
4203
+ function ArticleBodySkeleton({ className }) {
4204
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("mx-auto max-w-3xl animate-pulse space-y-4", className), children: [
4205
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-2/3 rounded bg-muted" }),
4206
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-56 rounded-xl bg-muted" })
4207
+ ] });
4208
+ }
4209
+ function ArticleCardPreview({
4210
+ tone,
4211
+ category,
4212
+ title,
4213
+ excerpt,
4214
+ author,
4215
+ initials,
4216
+ readTime,
4217
+ coverContent,
4218
+ coverClassName,
4219
+ className
4220
+ }) {
4221
+ return /* @__PURE__ */ jsxRuntime.jsxs(InteractiveCard, { className, children: [
4222
+ /* @__PURE__ */ jsxRuntime.jsx(ArticleCover, { tone, className: cn("h-32", coverClassName), children: coverContent }),
4223
+ /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "flex flex-1 flex-col p-4", children: [
4224
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "outline", className: "mb-3", children: category }),
4225
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold leading-snug", children: title }),
4226
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 line-clamp-2 text-sm text-muted-foreground", children: excerpt }),
4227
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-auto flex items-center justify-between gap-3 pt-5", children: [
4228
+ /* @__PURE__ */ jsxRuntime.jsx(ArticleByline, { author, initials, size: "sm", className: "min-w-0" }),
4229
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
4230
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "size-3" }),
4231
+ readTime
4232
+ ] })
4233
+ ] })
4234
+ ] })
4235
+ ] });
4236
+ }
4237
+ function FormField({ label, htmlFor, error, helperText, className, children }) {
4238
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-1.5", className), children: [
4239
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor, className: "text-xs", children: label }),
4240
+ children,
4241
+ error ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: error }) : helperText ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: helperText }) : null
4242
+ ] });
4243
+ }
4244
+ function FormActions({
4245
+ status,
4246
+ cancelLabel = "Cancel",
4247
+ onCancel,
4248
+ cancelDisabled,
4249
+ submitLabel,
4250
+ submitDisabled,
4251
+ className
4252
+ }) {
4253
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4254
+ "div",
4255
+ {
4256
+ className: cn(
4257
+ "flex items-center gap-2 border-t border-border pt-(--designkit-panel-gap)",
4258
+ status ? "justify-between" : "justify-end",
4259
+ className
4260
+ ),
4261
+ children: [
4262
+ status && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", role: "status", children: status }),
4263
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4264
+ /* @__PURE__ */ jsxRuntime.jsx(
4265
+ Button,
4266
+ {
4267
+ type: "button",
4268
+ variant: "outline",
4269
+ size: "sm",
4270
+ className: "h-8 text-xs",
4271
+ onClick: onCancel,
4272
+ disabled: cancelDisabled,
4273
+ children: cancelLabel
4274
+ }
4275
+ ),
4276
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", size: "sm", className: "h-8 text-xs", disabled: submitDisabled, children: submitLabel })
4277
+ ] })
4278
+ ]
4279
+ }
4280
+ );
4281
+ }
4123
4282
  var STYLE_ID = "designkit-vars";
4124
4283
  function buildTokenMap({
4125
4284
  radius,
@@ -4329,6 +4488,12 @@ exports.AlertDialogOverlay = AlertDialogOverlay;
4329
4488
  exports.AlertDialogPortal = AlertDialogPortal;
4330
4489
  exports.AlertDialogTitle = AlertDialogTitle;
4331
4490
  exports.AlertDialogTrigger = AlertDialogTrigger;
4491
+ exports.ArticleBody = ArticleBody;
4492
+ exports.ArticleBodySkeleton = ArticleBodySkeleton;
4493
+ exports.ArticleByline = ArticleByline;
4494
+ exports.ArticleCardPreview = ArticleCardPreview;
4495
+ exports.ArticleCover = ArticleCover;
4496
+ exports.ArticleToc = ArticleToc;
4332
4497
  exports.Avatar = Avatar;
4333
4498
  exports.AvatarBadge = AvatarBadge;
4334
4499
  exports.AvatarFallback = AvatarFallback;
@@ -4375,8 +4540,11 @@ exports.DropdownMenuSubContent = DropdownMenuSubContent;
4375
4540
  exports.DropdownMenuSubTrigger = DropdownMenuSubTrigger;
4376
4541
  exports.DropdownMenuTrigger = DropdownMenuTrigger;
4377
4542
  exports.EmptyState = EmptyState;
4543
+ exports.FormActions = FormActions;
4544
+ exports.FormField = FormField;
4378
4545
  exports.FormWizardBodyTemplate = FormWizardBodyTemplate;
4379
4546
  exports.Input = Input;
4547
+ exports.InteractiveCard = InteractiveCard;
4380
4548
  exports.Label = Label;
4381
4549
  exports.ListDetailBodyTemplate = ListDetailBodyTemplate;
4382
4550
  exports.LoginBodyTemplate = LoginBodyTemplate;