@dextinity/agent-features 2.0.0-canary-20260806092023 → 10.0.0-beta.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.
- package/package.json +2 -2
- package/skills/dev-pm/SKILL.md +1 -1
- package/skills/dextinity-admin-ui/SKILL.md +57 -5
- package/skills/dextinity-mail-react/SKILL.md +31 -5
- package/skills/dextinity-mail-react/references/components-and-theme.md +22 -5
- package/skills/dextinity-major-migration/SKILL.md +3 -3
- package/skills/dextinity-minor-update/SKILL.md +12 -12
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dextinity/agent-features",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0-beta.0",
|
|
4
4
|
"description": "Agent features (skills and rules) for Dextinity projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"directory": "packages/agent-features",
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/vivid-planet/
|
|
8
|
+
"url": "https://github.com/vivid-planet/dextinity"
|
|
9
9
|
},
|
|
10
10
|
"license": "BSD-2-Clause",
|
|
11
11
|
"files": [
|
package/skills/dev-pm/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: Run, restart, stop, and inspect logs/status of long-running develop
|
|
|
5
5
|
|
|
6
6
|
# dev-pm Skill
|
|
7
7
|
|
|
8
|
-
`dev-pm` (
|
|
8
|
+
`dev-pm` (`dev-process-manager`) supervises long-running dev processes (servers, watchers, codegen, storybook, docker, …). Available scripts and groups are defined in `dev-pm.config.ts` at the repo root — read it to discover what can be started.
|
|
9
9
|
|
|
10
10
|
## Critical rules
|
|
11
11
|
|
|
@@ -29,10 +29,11 @@ after the system genuinely can't express what you need.
|
|
|
29
29
|
3. **Consistency.** Every screen built from the same components and tokens looks and behaves the
|
|
30
30
|
same way.
|
|
31
31
|
|
|
32
|
-
This holds **even when a project's design deliberately differs** from the current library
|
|
33
|
-
|
|
34
|
-
configuring the theme — not by re-styling
|
|
35
|
-
explicitly instructed, or when no component, prop,
|
|
32
|
+
This holds **even when a project's design deliberately differs** from the current library defaults —
|
|
33
|
+
a permanent design decision, not a gap a later library upgrade will close. Prefer the Dextinity component
|
|
34
|
+
or token, and apply that project-specific difference by configuring the theme — not by re-styling
|
|
35
|
+
individual components. Add custom styling only when explicitly instructed, or when no component, prop,
|
|
36
|
+
or token can produce the result.
|
|
36
37
|
|
|
37
38
|
## Decision framework
|
|
38
39
|
|
|
@@ -291,7 +292,7 @@ Don't use `Grid` or `Stack` to lay out form fields: Dextinity stacks them vertic
|
|
|
291
292
|
grouped with `FieldSet` or `FormSection`.
|
|
292
293
|
|
|
293
294
|
`sx` is fine for an occasional layout property that no `Stack` or `Grid` prop covers, such as
|
|
294
|
-
`flexGrow`.
|
|
295
|
+
`flexGrow`. On your own markup, it is not for visual styling — that goes through `styled()`.
|
|
295
296
|
|
|
296
297
|
### Page structure: `MainContent`, `Toolbar`, and their parts
|
|
297
298
|
|
|
@@ -490,3 +491,54 @@ import { Delete } from "@dextinity/admin-icons";
|
|
|
490
491
|
|
|
491
492
|
<Delete fontSize="small" color="error" />;
|
|
492
493
|
```
|
|
494
|
+
|
|
495
|
+
## Customizing an existing Dextinity Admin component
|
|
496
|
+
|
|
497
|
+
When a Dextinity Admin component needs to look or behave differently than its defaults, customize it
|
|
498
|
+
through the mechanisms it already supports: the component's own props, a per-slot `slotProps` prop,
|
|
499
|
+
and theme-level `styleOverrides` and `defaultProps`. A _slot_ is a named inner element of a component;
|
|
500
|
+
only `root` is universal — a component lists its own slot names on its props type. Which mechanism you
|
|
501
|
+
pick depends on whether you're changing behavior or appearance.
|
|
502
|
+
|
|
503
|
+
### Behavior
|
|
504
|
+
|
|
505
|
+
Start with the component's own props. To reach an inner element, use `slotProps`: it forwards props
|
|
506
|
+
to a named slot, letting you override that slot's props. This configures the component rather than
|
|
507
|
+
restyling it.
|
|
508
|
+
|
|
509
|
+
```tsx
|
|
510
|
+
// Override an inner slot's props — here, disable the button behind the content
|
|
511
|
+
<ContentOverflow slotProps={{ clickableContent: { disabled: true } }}>{children}</ContentOverflow>
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### Appearance
|
|
515
|
+
|
|
516
|
+
To change how a Dextinity component looks, configure the theme rather than the component itself — the core
|
|
517
|
+
principle's rule for a project-specific design difference. `createDextinityTheme`'s `components` map takes
|
|
518
|
+
a `DextinityAdmin*` key (MUI components use their `Mui*` key); `styleOverrides` restyles a component's
|
|
519
|
+
slots and `defaultProps` sets default prop values, such as swapping an icon through `iconMapping`.
|
|
520
|
+
Both apply to every instance, so the deviation stays consistent and is defined in one reviewable place.
|
|
521
|
+
|
|
522
|
+
Styling a single instance directly is the rare exception — for a change genuinely specific to that
|
|
523
|
+
instance, or when you're explicitly told to. Which tool you use is then the same as anywhere else:
|
|
524
|
+
`sx` (or `slotProps.<slot>.sx` for a slot) for small layout, `styled()` for other custom styling, per
|
|
525
|
+
the styling section above. Use this only for a true single-instance change; a difference that recurs
|
|
526
|
+
belongs in the theme, not repeated on each instance.
|
|
527
|
+
|
|
528
|
+
```tsx
|
|
529
|
+
// Avoid — a styled() wrapper for a design difference that belongs in the theme
|
|
530
|
+
const HighlightedContentOverflow = styled(ContentOverflow)`
|
|
531
|
+
background-color: ${({ theme }) => theme.palette.grey[50]};
|
|
532
|
+
`;
|
|
533
|
+
|
|
534
|
+
// Prefer — configure the theme, applied to every instance
|
|
535
|
+
const theme = createDextinityTheme({
|
|
536
|
+
components: {
|
|
537
|
+
DextinityAdminContentOverflow: {
|
|
538
|
+
styleOverrides: {
|
|
539
|
+
root: ({ theme }) => ({ backgroundColor: theme.palette.grey[50] }),
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
});
|
|
544
|
+
```
|
|
@@ -41,7 +41,7 @@ This applies to seemingly simple things: `border-radius`, `background-image`, `f
|
|
|
41
41
|
|
|
42
42
|
### Library Documentation
|
|
43
43
|
|
|
44
|
-
Full documentation for `@dextinity/mail-react`: https://docs.
|
|
44
|
+
Full documentation for `@dextinity/mail-react`: https://cms-docs.dextinity.com/docs/features-modules/building-html-emails/
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
@@ -125,6 +125,24 @@ Always use `theme.breakpoints.*.belowMediaQuery` inside `registerStyles` instead
|
|
|
125
125
|
|
|
126
126
|
## Common Pitfalls
|
|
127
127
|
|
|
128
|
+
### Start Raw Content Inside a Column With `<tr>`
|
|
129
|
+
|
|
130
|
+
`mj-column` wraps every child in its own `<tr><td>` — except `MjmlRaw` content, which goes straight into the column's table unwrapped. A `<table>`, `<div>`, or `<img>` in that position ends up outside the column's table instead, and MJML reports no error. This covers the `Html*` components. Open with a `<tr>` and put the markup in a `<td>`:
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
<MjmlColumn>
|
|
134
|
+
<MjmlRaw>
|
|
135
|
+
<tr>
|
|
136
|
+
<td>{/* your raw markup */}</td>
|
|
137
|
+
</tr>
|
|
138
|
+
</MjmlRaw>
|
|
139
|
+
</MjmlColumn>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`HtmlText` is the exception: it renders the `<td>` itself, so a surrounding `<tr>` is all it needs — unless its `element` prop renders something else, which needs a `<td>` again.
|
|
143
|
+
|
|
144
|
+
`MjmlColumn` and `MjmlHero` are both affected — `MjmlSection` and `MjmlWrapper` already place their children inside a shared cell, so any root element is safe there. `MjmlDivider` supplies both the row and the cell; use it instead of a hand-wrapped `HtmlDivider` whenever you are in an `MjmlColumn`.
|
|
145
|
+
|
|
128
146
|
### Avoid Block-Level HTML Elements Inside Ending Tags
|
|
129
147
|
|
|
130
148
|
Don't use `<p>`, `<h1>`, `<h2>`, or other block-level HTML elements inside ending tags. They have wildly inconsistent default margins and spacing across email clients and add no rendering value in email HTML. Instead, use `<td>`, `<div>`, and `<span>` for structure, and build your typography hierarchy through `MjmlText`/`HtmlText` variants rather than HTML semantics. If a block-level element is truly unavoidable, always reset its margins inline: `style={{ margin: 0 }}`.
|
|
@@ -303,6 +321,8 @@ All components are imported from `@dextinity/mail-react` — never from `@faire/
|
|
|
303
321
|
| `MjmlPixelImageBlock` | re-exported `MjmlImage` | an `MjmlColumn` (standard MJML layout) |
|
|
304
322
|
| `HtmlPixelImageBlock` | raw `<img>` | raw HTML or MJML ending tags such as `MjmlRaw` |
|
|
305
323
|
|
|
324
|
+
Inside `MjmlRaw` in an `MjmlColumn`, `HtmlPixelImageBlock` needs its own `<tr>` and `<td>` — see _Start Raw Content Inside a Column With `<tr>`_ above.
|
|
325
|
+
|
|
306
326
|
```tsx
|
|
307
327
|
<MjmlSection indent>
|
|
308
328
|
<MjmlColumn>
|
|
@@ -361,6 +381,8 @@ export const { MjmlRichTextBlock, HtmlRichTextBlock } = createRichTextBlock({
|
|
|
361
381
|
| `MjmlRichTextBlock` | `MjmlText` | an `MjmlColumn` (standard MJML layout) |
|
|
362
382
|
| `HtmlRichTextBlock` | `HtmlText` (`<div>`) | raw HTML or MJML ending tags such as `MjmlRaw` |
|
|
363
383
|
|
|
384
|
+
Inside `MjmlRaw` in an `MjmlColumn`, `HtmlRichTextBlock` needs its own `<tr>` and `<td>` — see _Start Raw Content Inside a Column With `<tr>`_ above.
|
|
385
|
+
|
|
364
386
|
Usage sites pass only `data`:
|
|
365
387
|
|
|
366
388
|
```tsx
|
|
@@ -392,6 +414,8 @@ Key behaviors:
|
|
|
392
414
|
);
|
|
393
415
|
```
|
|
394
416
|
|
|
417
|
+
For a list block type, target `.<className> .richTextBlock__listItemText` instead of `> div` — the list's cells carry their own font styles, which outrank a rule on the block's element.
|
|
418
|
+
|
|
395
419
|
- **Multiple configurations per app.** Each factory call is independent — rename the destructured components per use case:
|
|
396
420
|
|
|
397
421
|
```tsx
|
|
@@ -426,9 +450,11 @@ Key behaviors:
|
|
|
426
450
|
});
|
|
427
451
|
```
|
|
428
452
|
|
|
429
|
-
- **Lists** render
|
|
453
|
+
- **Lists** render as a table inside one text component, with a row per item, a marker cell and a text cell — the indent and the marker gap are cell padding, which is the only spacing Outlook on Windows applies reliably.
|
|
454
|
+
- **List spacing** comes from the theme's `list.indent` (before the marker), `list.markerGap` (between the marker and the text) and `list.itemSpacing` (between items), all responsive and all applying to every list the block renders. To override it, register a rule scoped to a list's type or variant modifier with `{ inline: true }`, which has MJML write the declaration into the cell's `style` attribute at compile time so it also reaches Outlook.
|
|
455
|
+
- **List markers** come from the theme's `list.unorderedMarker` and `list.orderedMarker`, each either a fixed node (`unorderedMarker: "▪"`) or a function of the item's `index` and its list's `depth`.
|
|
430
456
|
- Spacing between blocks comes from the theme's `bottomSpacing` (the last block gets none); headings are styled text, not semantic `<h1>` elements.
|
|
431
|
-
- Rendered elements carry `richTextBlock__text`, `richTextBlock__list`, `richTextBlock__listItem`, and `richTextBlock__link` class names for targeting with `registerStyles`.
|
|
457
|
+
- Rendered elements carry `richTextBlock__text`, `richTextBlock__list`, `richTextBlock__listItem`, `richTextBlock__listItemMarker`, `richTextBlock__listItemText`, and `richTextBlock__link` class names for targeting with `registerStyles`. The list table also carries `richTextBlock__list--ordered` or `richTextBlock__list--unordered`, plus a modifier naming the text variant its items render with, such as `richTextBlock__list--variantBody`. Its rows carry `richTextBlock__listItem--itemSpacing`, or `richTextBlock__listItem--blockSpacing` on the last row when spacing follows the list. Its cells restate the text styles inline, so a rule targeting list text needs `!important`.
|
|
432
458
|
|
|
433
459
|
---
|
|
434
460
|
|
|
@@ -617,5 +643,5 @@ Storybook previews show how the email renders in a web browser, but email client
|
|
|
617
643
|
|
|
618
644
|
The `@dextinity/mail-react` package focuses on building email markup. For sending emails and managing templates in a Dextinity project:
|
|
619
645
|
|
|
620
|
-
- **Mail Templates Module** — server-side template registration, dependency injection, and sending. Integrates with `@dextinity/mail-react` via `renderMailHtml`. Docs: https://docs.
|
|
621
|
-
- **Mailer Module** — lower-level mail sending service. Docs: https://docs.
|
|
646
|
+
- **Mail Templates Module** — server-side template registration, dependency injection, and sending. Integrates with `@dextinity/mail-react` via `renderMailHtml`. Docs: https://cms-docs.dextinity.com/docs/features-modules/mail-templates-module/
|
|
647
|
+
- **Mailer Module** — lower-level mail sending service. Docs: https://cms-docs.dextinity.com/docs/features-modules/mailer-module/
|
|
@@ -43,11 +43,28 @@ const theme = createTheme({
|
|
|
43
43
|
sizes: {
|
|
44
44
|
contentIndentation: { default: 40, tablet: 30, mobile: 20 },
|
|
45
45
|
},
|
|
46
|
+
list: {
|
|
47
|
+
indent: { default: 24, tablet: 16, mobile: 8 },
|
|
48
|
+
},
|
|
46
49
|
});
|
|
47
50
|
```
|
|
48
51
|
|
|
49
52
|
The `default` key provides the base value (rendered inline). Other keys generate media query overrides automatically.
|
|
50
53
|
|
|
54
|
+
### List Markers
|
|
55
|
+
|
|
56
|
+
`list.unorderedMarker` and `list.orderedMarker` set the markers of the lists the RichText block renders: a fixed node, or a function receiving the item's zero-based `index` and the `depth` of its list. Use plain HTML and React elements, not MJML components:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
const theme = createTheme({
|
|
60
|
+
list: {
|
|
61
|
+
unorderedMarker: ({ depth }) => ["▪", "–", "·"][depth % 3],
|
|
62
|
+
// 97 is the code of "a", so nested items are lettered a., b., c.
|
|
63
|
+
orderedMarker: ({ index, depth }) => (depth === 0 ? `${index + 1}.` : `${String.fromCharCode(97 + index)}.`),
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
51
68
|
---
|
|
52
69
|
|
|
53
70
|
## Module Augmentation Interfaces
|
|
@@ -279,13 +296,13 @@ Themed text for use inside ending tags (`MjmlText`, `MjmlRaw`) or custom HTML st
|
|
|
279
296
|
**CSS classes:** `.htmlText`, `.htmlText--{variant}`, `.htmlText--bottomSpacing`.
|
|
280
297
|
|
|
281
298
|
```tsx
|
|
282
|
-
<
|
|
283
|
-
<
|
|
299
|
+
<MjmlColumn>
|
|
300
|
+
<MjmlRaw>
|
|
284
301
|
<tr>
|
|
285
|
-
<HtmlText variant="body">Themed text
|
|
302
|
+
<HtmlText variant="body">Themed text in a row of the column's table</HtmlText>
|
|
286
303
|
</tr>
|
|
287
|
-
</
|
|
288
|
-
</
|
|
304
|
+
</MjmlRaw>
|
|
305
|
+
</MjmlColumn>
|
|
289
306
|
|
|
290
307
|
<MjmlText>
|
|
291
308
|
<HtmlText element="div" variant="caption">Rendered as a div</HtmlText>
|
|
@@ -14,10 +14,10 @@ Do NOT use for minor or patch upgrades, or for ongoing feature work on a project
|
|
|
14
14
|
## Locate the migration guide
|
|
15
15
|
|
|
16
16
|
1. **Find out the target major** from the user if not specified.
|
|
17
|
-
2. **Browse the index:** https://github.com/vivid-planet/
|
|
17
|
+
2. **Browse the index:** https://github.com/vivid-planet/dextinity/tree/main/docs/docs/7-migration-guide — use a GitHub MCP tool if available, otherwise `WebFetch`.
|
|
18
18
|
3. **Download the raw Markdown** so all content is in context:
|
|
19
19
|
```
|
|
20
|
-
https://raw.githubusercontent.com/vivid-planet/
|
|
20
|
+
https://raw.githubusercontent.com/vivid-planet/dextinity/refs/heads/main/docs/docs/7-migration-guide/migration-from-v{N}-to-v{N+1}.md
|
|
21
21
|
```
|
|
22
22
|
4. **If no guide exists** for the target version, stop and tell the user. Don't migrate without an official guide.
|
|
23
23
|
|
|
@@ -73,7 +73,7 @@ Record the resolved site list durably (e.g. a note on the first `TaskCreate` tas
|
|
|
73
73
|
|
|
74
74
|
If a step is ambiguous or doesn't match the project, consult before guessing:
|
|
75
75
|
|
|
76
|
-
- **https://github.com/vivid-planet/
|
|
76
|
+
- **https://github.com/vivid-planet/dextinity** — the monorepo. Check the source of the package the guide discusses for the new public API shape.
|
|
77
77
|
- **https://github.com/vivid-planet/comet-starter** — the canonical reference project, always kept on the current major. Use it for questions like "how should `tsconfig.json` look after this migration?"
|
|
78
78
|
|
|
79
79
|
Prefer the GitHub MCP; fall back to `WebFetch` on `raw.githubusercontent.com`. If still unclear, ask the user — don't guess.
|
|
@@ -16,7 +16,7 @@ Two rules hold across every `@dextinity/*` core package in the project, before a
|
|
|
16
16
|
- **Pinned versions only.** Every core `@dextinity/*` entry must be an exact version (e.g. `8.21.0`), never a range (`^8.21.0`, `~8.21.0`, `>=…`). If you see a caret or tilde on a core package, the project is in a broken state — stop and tell the user.
|
|
17
17
|
- **All core packages on the same version.** Every core `@dextinity/*` package in the project must be pinned to the same version across every `package.json`. There is no supported mix-and-match.
|
|
18
18
|
|
|
19
|
-
These rules apply only to the core set (packages released together from the Dextinity monorepo).
|
|
19
|
+
These rules apply only to the core set (packages released together from the Dextinity monorepo). Any other `@dextinity/*` package a project happens to depend on is out of scope — see Step 1.
|
|
20
20
|
|
|
21
21
|
## When to use
|
|
22
22
|
|
|
@@ -60,8 +60,8 @@ grep -n '"@dextinity/' package.json api/package.json admin/package.json \
|
|
|
60
60
|
|
|
61
61
|
Notes:
|
|
62
62
|
|
|
63
|
-
- Not every `@dextinity/*`
|
|
64
|
-
- Use the invariants to tell core from
|
|
63
|
+
- Not every `@dextinity/*` dependency you find follows the core release cadence. **Only** bump packages whose current version matches the core Dextinity version (the one shared by `@dextinity/cms-api`, `@dextinity/admin`, `@dextinity/site-nextjs`, etc.). Leave the others untouched.
|
|
64
|
+
- Use the invariants to tell core from non-core: core packages are all pinned to the same exact version, with no caret or tilde. Anything with a range or a different version is not core — verify before touching it.
|
|
65
65
|
- If you find core packages on different versions, or any core package using a range (`^`, `~`), the project violates the invariants. Stop and tell the user — don't paper over it by bumping.
|
|
66
66
|
|
|
67
67
|
Confirm the **current major** from the version string (e.g. `8.20.4` → major `8`).
|
|
@@ -100,7 +100,7 @@ grep -n '<OLD_VERSION>' package.json api/package.json admin/package.json \
|
|
|
100
100
|
|
|
101
101
|
If every match is a `@dextinity/*` line, you can safely edit each file. If there are non-`@dextinity` matches, edit the `@dextinity` lines individually.
|
|
102
102
|
|
|
103
|
-
**Do not touch** packages
|
|
103
|
+
**Do not touch** `@dextinity/*` packages that don't share the core version — see Step 1.
|
|
104
104
|
|
|
105
105
|
---
|
|
106
106
|
|
|
@@ -181,11 +181,11 @@ Tell the user:
|
|
|
181
181
|
|
|
182
182
|
## Common pitfalls
|
|
183
183
|
|
|
184
|
-
| Pitfall
|
|
185
|
-
|
|
|
186
|
-
| Picking a canary/beta as "newest"
|
|
187
|
-
| Bumping
|
|
188
|
-
| Forgetting the root `package.json`
|
|
189
|
-
| Assuming "up to date" means the install did nothing
|
|
190
|
-
| Running installs in parallel in a sandbox
|
|
191
|
-
| Crossing a major version
|
|
184
|
+
| Pitfall | How to avoid |
|
|
185
|
+
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
186
|
+
| Picking a canary/beta as "newest" | Filter out any version containing `-` in Step 2. |
|
|
187
|
+
| Bumping a non-core `@dextinity/*` package by accident | Only bump packages pinned to the shared core version — see Step 1. |
|
|
188
|
+
| Forgetting the root `package.json` | The repo root has its own `package.json` with `@dextinity/cli`. Always include it in the grep. |
|
|
189
|
+
| Assuming "up to date" means the install did nothing | It means the lockfile already satisfies the new range. Verify with `grep` against the lockfile. |
|
|
190
|
+
| Running installs in parallel in a sandbox | If `&` backgrounding fails, just run the installs sequentially. Takes a bit longer, works reliably. |
|
|
191
|
+
| Crossing a major version | This skill is minor/patch only. Stop and warn the user. |
|