@panphora/hyper-cms 0.11.5 → 0.12.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/README.md +91 -6
- package/dist/hypercms.min.js +169 -84
- package/package.json +5 -3
- package/src/apply-loop.js +3 -2
- package/src/catalogs/colors.js +293 -0
- package/src/catalogs/fonts.js +126 -0
- package/src/catalogs/index.js +3 -0
- package/src/catalogs/variant-icons.js +24 -0
- package/src/color-control.js +196 -0
- package/src/events.js +25 -2
- package/src/font-control.js +142 -0
- package/src/fonts-link.js +83 -0
- package/src/form-builder.js +85 -3
- package/src/form-rules.js +48 -3
- package/src/hypercms.js +111 -21
- package/src/page-root.js +28 -0
- package/src/refresh.js +4 -1
- package/src/session.js +51 -3
- package/src/targets.js +55 -13
- package/src/templates.js +100 -6
- package/src/theme/pixel-quiet.overrides.css +91 -0
- package/src/theme.generated.css +91 -0
- package/src/toggle.js +80 -296
- package/src/variant-control.js +46 -0
- package/src/views/inline-layer.js +71 -15
- package/src/views/inline.js +87 -17
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ cms.open({ rules: { title: '.title' } }) // a literal rules object, passed by h
|
|
|
56
56
|
|
|
57
57
|
## Auto-open with `?cms=true`
|
|
58
58
|
|
|
59
|
-
Load any hypercms page with `?cms=true` in the URL and the CMS opens by itself once the DOM is ready — no trigger, no `cms.open()` call. The auto-open uses the host defaults (`document
|
|
59
|
+
Load any hypercms page with `?cms=true` in the URL and the CMS opens by itself once the DOM is ready — no trigger, no `cms.open()` call. The auto-open uses the host defaults (the whole `document` as `pageRoot`, `document.body` as `mountTo`), and it never double-mounts: if your page also calls `cms.open()`, the second open is a no-op.
|
|
60
60
|
|
|
61
61
|
When the user closes the CMS, hypercms rewrites the param to `cms=false` via `history.replaceState` (the param is kept, no reload), so refreshing or sharing the post-close URL does not auto-reopen:
|
|
62
62
|
|
|
@@ -96,12 +96,25 @@ The full grammar lives in the [hyper-html-api docs](https://github.com/panphora/
|
|
|
96
96
|
| Object array | `"products": [".product", { "name": ".name" }]` | list of cards |
|
|
97
97
|
| Nested | object arrays inside object arrays | recurses |
|
|
98
98
|
|
|
99
|
+
## Choosing the view
|
|
100
|
+
|
|
101
|
+
A page declares which editor it opens in, on its rules tag:
|
|
102
|
+
|
|
103
|
+
```html
|
|
104
|
+
<script data-rules-name="cms" data-rules-version="1" data-cms-view="inline" type="application/json">…</script>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`inline` edits text where it sits on the page and opens small popovers for everything else.
|
|
108
|
+
`sidebar` (also what you get with no attribute) opens the form in a side panel. The floating
|
|
109
|
+
toggle opens and closes whichever view the page declares; it does not switch between them.
|
|
110
|
+
`cms.open({ view: 'inline' })` still overrides the declaration for one session.
|
|
111
|
+
|
|
99
112
|
## Field controls
|
|
100
113
|
|
|
101
114
|
How the sidebar picks a control for each leaf, in order:
|
|
102
115
|
|
|
103
|
-
1. If the page element the rule points at carries `data-hcms-component`, that control wins. Explicit beats inferred. Values: `checkbox`, `toggle`, `select`, `radio`, `textarea`, `number`, `image`, `file` on scalar fields, `chips` on list containers.
|
|
104
|
-
2. Otherwise a rule ending in `@src` gets the **image upload** control,
|
|
116
|
+
1. If the page element the rule points at carries `data-hcms-component`, that control wins. Explicit beats inferred. Values: `checkbox`, `toggle`, `select`, `radio`, `textarea`, `number`, `image`, `file`, `color`, `font`, `variant` on scalar fields, `chips` on list containers.
|
|
117
|
+
2. Otherwise a rule ending in `@src` gets the **image upload** control, a rule ending in `@checked` gets a **checkbox**, a rule ending in `@--color` or `@--color-<name>` gets the **color** control, and a rule ending in `@--font` or `@--font-<name>` gets the **font** control.
|
|
105
118
|
3. Otherwise the rule's shape picks one of the defaults below, unless a [custom template](#custom-form-templates) overrides it.
|
|
106
119
|
|
|
107
120
|
A custom `<template data-hcms-tpl>` matching the field's path always outranks a named component (the author's template is the stronger signal); when that happens the sidebar logs a `console.info` naming the shadowed component.
|
|
@@ -194,6 +207,76 @@ A "Choose" button uploads the file, writes the URL into the `a href`, and shows
|
|
|
194
207
|
|
|
195
208
|
Use it for: a resume PDF, a downloadable spec or whitepaper, a press kit — links whose target the owner should replace by picking a file.
|
|
196
209
|
|
|
210
|
+
### Page style: colors, fonts and layouts (`color`, `font`, `variant`)
|
|
211
|
+
|
|
212
|
+
These three controls change how a page looks rather than what it says. They write CSS custom
|
|
213
|
+
properties or attributes, and the page's own CSS decides what those do.
|
|
214
|
+
|
|
215
|
+
**The `@--name` rule form** reads and writes one CSS custom property in an element's `style`
|
|
216
|
+
attribute, leaving every other declaration alone:
|
|
217
|
+
|
|
218
|
+
```html
|
|
219
|
+
<html style="--color-accent: #0284c7; --font-body: 'Inter', ui-sans-serif, system-ui, sans-serif">
|
|
220
|
+
<style>
|
|
221
|
+
a, .button { color: var(--color-accent); }
|
|
222
|
+
body { font-family: var(--font-body); }
|
|
223
|
+
</style>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{ "theme": { "accent": "html@--color-accent", "body": "html@--font-body" } }
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Writes through the guarded paths (`writeDocument`, `applyData`, the JSON API) accept a custom
|
|
231
|
+
property only when its value is plain: at most 200 characters, no `;`, braces, angle brackets or
|
|
232
|
+
backslash, and no `url()`, `image()` or similar functions.
|
|
233
|
+
|
|
234
|
+
**Several controls on one element.** Attributes scoped to a property name apply to that rule
|
|
235
|
+
only, so one element can carry a layout choice and a background color:
|
|
236
|
+
|
|
237
|
+
```html
|
|
238
|
+
<section id="features" data-layout="3" style="--color-section-bg: #f8fafc"
|
|
239
|
+
data-hcms-component:data-layout="variant"
|
|
240
|
+
data-hcms-options:data-layout="1:cols-1 2:cols-2 3:cols-3"
|
|
241
|
+
data-hcms-options:--color-section-bg="slate-50 slate-100 sky-50 custom">
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
`data-hcms-component:<prop>`, `data-hcms-options:<prop>` and `data-hcms-crop:<prop>` win over the
|
|
245
|
+
plain attribute for the rule ending in `@<prop>`. A plain attribute never applies to an `@--name`
|
|
246
|
+
rule.
|
|
247
|
+
|
|
248
|
+
**Color** (`color`, inferred for `@--color` and `@--color-*`). A swatch grid of the full
|
|
249
|
+
Tailwind palette (26 hues by 11 shades) plus a custom picker. `data-hcms-options` narrows it:
|
|
250
|
+
color ids (`sky-600`), whole hues (`sky`), whole shades (`500`), plain CSS colors, and `custom`
|
|
251
|
+
to keep the custom picker, which a narrowed list hides unless you add it. A clear button empties
|
|
252
|
+
the property so the page falls back to its own CSS.
|
|
253
|
+
|
|
254
|
+
**Font** (`font`, inferred for `@--font` and `@--font-*`). A list of 40 Google Fonts, each shown
|
|
255
|
+
in its own face, plus the system stacks. `data-hcms-options` narrows it: font slugs (`inter`),
|
|
256
|
+
groups (`sans`, `serif`, `display`, `mono`), and `system`. The CMS keeps one
|
|
257
|
+
`<link data-hcms-fonts>` in the head that loads exactly the families the page's font fields hold,
|
|
258
|
+
and removes it when none do.
|
|
259
|
+
|
|
260
|
+
**Variant** (`variant`, never inferred). A row of icon tiles, one per option, backed by native
|
|
261
|
+
radios. Each `data-hcms-options` token is `value:icon` or a bare value; the icons are `cols-1`,
|
|
262
|
+
`cols-2`, `cols-3`, `cols-4`, `media-left`, `media-right`, `media-top`, `list`, `cards`,
|
|
263
|
+
`centered`, `card-flat` and `card-raised`. Choosing one writes only the attribute, so the layout
|
|
264
|
+
lives in your CSS:
|
|
265
|
+
|
|
266
|
+
```css
|
|
267
|
+
#features { display: grid; gap: 1.5rem; }
|
|
268
|
+
#features[data-layout="2"] { grid-template-columns: repeat(2, 1fr); }
|
|
269
|
+
#features[data-layout="3"] { grid-template-columns: repeat(3, 1fr); }
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**Where they show up.** In the sidebar, style fields bound to `html`, `body` or `:root` gather
|
|
273
|
+
in a **Page style** group at the top, and inside every other group and card the style fields
|
|
274
|
+
come first. In the inline view they are never hover targets: a section's style fields open from
|
|
275
|
+
a **Style** chip in its top-left corner, a list row's from **Style** in its gear menu, and the
|
|
276
|
+
page's from the **Page style** button in the bar.
|
|
277
|
+
|
|
278
|
+
Living example: `demo/theme.html`.
|
|
279
|
+
|
|
197
280
|
### Everything else: custom templates
|
|
198
281
|
|
|
199
282
|
Anything past the built-ins — multi-select, sliders, color pickers, bespoke layouts, option labels that differ from their values — is [custom template](#custom-form-templates) territory over the same machinery. Living examples: `demo/index.html` (the `quantity` template, a wildcard-path override) and `demo/pixel-quiet.html` (the `bio` template).
|
|
@@ -287,7 +370,7 @@ cms.api.removeItem(itemPath) // drop an item by index
|
|
|
287
370
|
|
|
288
371
|
| Option | Default | Effect |
|
|
289
372
|
|---|---|---|
|
|
290
|
-
| `pageRoot` | `document
|
|
373
|
+
| `pageRoot` | `document` | Where extract/apply run. The whole document by default, so a rule can bind `html` or `body` themselves. Events still report `document.body` as `pageRoot`. |
|
|
291
374
|
| `mountTo` | `document.body` | Where the shell DOM mounts. Can be a descendant of pageRoot. |
|
|
292
375
|
| `side` | `'right'` | `'right'` or `'left'`. |
|
|
293
376
|
| `overlay` | `false` | If true, sidebar covers the page; if false, page content gets a padding offset. |
|
|
@@ -377,8 +460,10 @@ In hyperclayjs apps, drag works out of the box (hypercms's object-array template
|
|
|
377
460
|
|
|
378
461
|
## The floating toggle
|
|
379
462
|
|
|
380
|
-
|
|
381
|
-
|
|
463
|
+
On a page that has a cms rules tag, hypercms injects a floating "Edit content"
|
|
464
|
+
button in the bottom-right corner: in edit mode, and on a ClayJS page whenever
|
|
465
|
+
ClayJS lets the visitor edit (in view too), where pressing it switches to edit
|
|
466
|
+
and then opens the CMS. It is runtime-only chrome: it
|
|
382
467
|
carries `no-save`, `snapshot-remove` and `save-ignore`, so it never reaches the
|
|
383
468
|
saved file and never marks the page dirty.
|
|
384
469
|
|