@plitzi/sdk-shared 0.38.9 → 0.38.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.
- package/CHANGELOG.md +256 -0
- package/dist/actions/validateDocument.mjs +2 -1
- package/dist/authoring/declare.d.ts +8 -0
- package/dist/dataSource/getBindingsDetails.mjs +20 -20
- package/dist/index.mjs +24 -24
- package/dist/realtime/client.d.ts +6 -3
- package/dist/realtime/client.mjs +19 -17
- package/dist/realtime/index.d.ts +1 -1
- package/dist/realtime/index.mjs +4 -4
- package/dist/realtime/presence.mjs +1 -1
- package/dist/realtime/topics.d.ts +6 -0
- package/dist/realtime/topics.mjs +2 -2
- package/dist/schema/index.mjs +3 -3
- package/dist/schema/serverElements.d.ts +26 -5
- package/dist/schema/serverElements.mjs +21 -13
- package/dist/style/useElementSize.d.ts +16 -0
- package/dist/style/useElementSize.mjs +20 -0
- package/dist/theme/ThemeProvider.mjs +47 -38
- package/dist/theme/ThemeScope.d.ts +21 -1
- package/dist/theme/ThemeScope.mjs +7 -4
- package/dist/theme/index.mjs +5 -5
- package/dist/theme/themeStore.d.ts +6 -0
- package/dist/theme/themeStore.mjs +7 -4
- package/dist/theme/useTheme.mjs +4 -4
- package/dist/types/ActionTypes.d.ts +19 -3
- package/dist/types/RealtimeTypes.d.ts +14 -1
- package/dist/types/ServerTypes.d.ts +6 -1
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,261 @@
|
|
|
1
1
|
# @plitzi/sdk-shared
|
|
2
2
|
|
|
3
|
+
## 0.38.11
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- cadf70a: - **`server.cache.invalidate` drops what a page is rendered from** (`@plitzi/sdk-server`): the pages, the RSC answers
|
|
8
|
+
and the schema data they are rendered from go together. It dropped the pages alone, and the next request rendered
|
|
9
|
+
the same page again from the schema still cached under the same key — a publish that invalidated the space changed
|
|
10
|
+
nothing until the schema's TTL ran out. `clear()` and `size` cover the three. A filter on `hostname` drops the schema
|
|
11
|
+
data too, which belongs to no one host. `server.cache` is `null` only when nothing is cached (`cacheTtlMs: 0` and
|
|
12
|
+
`rsc.cacheTtlMs: 0`).
|
|
13
|
+
|
|
14
|
+
## Style inspector
|
|
15
|
+
- **Finds a property** (`@plitzi/sdk-style`): a search above the categories narrows them to the ones that edit what was
|
|
16
|
+
typed — a CSS name in any order of its words (`border radius` finds the four corners), a category's title, or a
|
|
17
|
+
common word for it (`bg`, `rounded`) — opens them, and shows the advanced rows when the match lives there. Escape
|
|
18
|
+
clears it. The categories' properties live in one list (`categoryKeys.ts`) that the dots, the advanced hint and the
|
|
19
|
+
search all read.
|
|
20
|
+
- **Rows that fit**: a section with more than two controls puts its label above them and lays them out in as many
|
|
21
|
+
columns as the panel is wide, instead of one row where every label was cut (`Appearan…`, `Cell Spaci…`, the five
|
|
22
|
+
scroll-snap controls). A row's label column is 80px.
|
|
23
|
+
- **Where a value comes from, said quietly**: the label's tint keeps its four meanings — set here, from a token, bound
|
|
24
|
+
to data, inherited — without the solid blocks of colour; hovering says which (an inherited one names its selector and
|
|
25
|
+
breakpoint) and that a click resets it, the click shows it by striking the label through. The footer's info icon
|
|
26
|
+
holds the legend, and its arrow folds every category.
|
|
27
|
+
- **What is being edited**: an "Editing … › Hover" line under the pickers whenever the rules being written are not the
|
|
28
|
+
selector's plain ones, with a button back to them. Ancestor, pseudo-element and condition fold behind a toggle —
|
|
29
|
+
never while one is in use.
|
|
30
|
+
- The class being edited is the panel's one strong mark (violet), the element's type defaults a softer one; the tools'
|
|
31
|
+
tabs fit the panel and are reachable from the keyboard.
|
|
32
|
+
|
|
33
|
+
- **Lists edited in a popover, all alike**: box and text shadows, transforms, transitions and filters share one row
|
|
34
|
+
(the CSS it writes, a swatch, a remove button) and one popover (a title, a close button, Escape, the focus moved
|
|
35
|
+
into it). What none of them could read is now kept and edited as text instead of being replaced with a default — a
|
|
36
|
+
token for the whole value, `drop-shadow(…)`, `url(#…)`.
|
|
37
|
+
- **Values read the way CSS writes them**: a shadow with two, three or four lengths and its color on either end;
|
|
38
|
+
`rgba(…)` inside text shadows and filters no longer split; negative shadow offsets accepted; a transition with any
|
|
39
|
+
of its parts left out; brightness, contrast and saturation past 1. Transition presets are written as CSS — the
|
|
40
|
+
preset names (`easeInQuad`) made the browser drop the whole declaration — the curve can be dragged into one of your
|
|
41
|
+
own, and the preview stops with the editor. `font-color` (not CSS) became `color`.
|
|
42
|
+
- **Background layers keep what they hold**: a repeating gradient (now a switch), a radial gradient's explicit size, a
|
|
43
|
+
token or `image-set()` as a layer (a "Custom (CSS)" layer), a one-value position read as CSS reads it (`20%` is
|
|
44
|
+
`20% center`), lists shorter than the layers repeated as CSS repeats them, an unset repeat read as tiling, two-position
|
|
45
|
+
stops, negative angles — every one of them was rewritten on the next edit of any layer. Defaults are no longer
|
|
46
|
+
written back, and "Token values" no longer bakes resolved tokens into the layers.
|
|
47
|
+
- **A layer's editor in two halves** — what it draws, then where it goes (size, position, tile, attachment, clip,
|
|
48
|
+
which now offers `text`). The gradient's stops sit on one bar, each a handle that drags or moves with the arrow keys;
|
|
49
|
+
the stop's color and position below it. Previews and swatches resolve the space's tokens.
|
|
50
|
+
- Spacing tells margin (dashed, outside) from padding; Border's sides are labelled and readable in the dark theme; a
|
|
51
|
+
class's menu says what each action does to whom; the Style Manager opens at a size that holds both columns.
|
|
52
|
+
|
|
53
|
+
## Builder
|
|
54
|
+
- **Shortcuts**: `?` shows every shortcut the builder answers to — the same list the "Nothing selected" card teaches
|
|
55
|
+
from — and ⌘\ / Ctrl+\ hides both side panels for the canvas alone and brings back the ones that were open. Both
|
|
56
|
+
work with the canvas focused.
|
|
57
|
+
- **Panels keep their width**: each side panel opens at the width it was left at; the right one starts at 380px.
|
|
58
|
+
- **Text no smaller than 11px** across the builder's panels (it went down to 10px in fifty places).
|
|
59
|
+
|
|
60
|
+
## Realtime
|
|
61
|
+
- **A page hears what it sent when it asks to** (`@plitzi/sdk-shared`, `@plitzi/sdk-server`, `@plitzi/sdk-elements`):
|
|
62
|
+
`publishOn('room', 'react', data, { echo: true })`, `useChannel().publish(type, data, { echo: true })` and the
|
|
63
|
+
channel's `publish` callback (`echo`) hand the message back to the page that sent it too, once the server took it —
|
|
64
|
+
stamped like everyone's, with `echo: true`, its `from` the channel's `me`. Without it a page still never hears its
|
|
65
|
+
own messages, and the docs said "every page on its topic hears it": they now say every OTHER page. Presence never
|
|
66
|
+
echoes.
|
|
67
|
+
- **A topic is opened only once it names one** (`@plitzi/sdk-elements`): `useChannel` — and so the `channel` element —
|
|
68
|
+
opens a topic only when a channel of the space covers it, by the same `matchChannel` the server decides by. A topic
|
|
69
|
+
written from data that has not arrived (`room:` while its provider loads, or its template still as text) asked the
|
|
70
|
+
server for both, was refused with a 403 and a console error on every load, and is now waited for.
|
|
71
|
+
- **Pages that watch** (`@plitzi/sdk-server`, `@plitzi/cli`): a connection whose page carries the `plitzi-observer`
|
|
72
|
+
cookie hears its topics and says nothing on them — no `$join`, no presence, its publishes taken and dropped.
|
|
73
|
+
`page check`, `page shot` and `verify` load pages that way, so checking a live site is no longer a visitor walking
|
|
74
|
+
into a room (`X walked in`, a member more in every picture). `--presence` takes part as a visitor does.
|
|
75
|
+
|
|
76
|
+
## Authoring
|
|
77
|
+
- **`template-in-value`** (refused): a `{{ }}` inside an attribute that is an object or a list — a provider's
|
|
78
|
+
`input`, a list's `items`, a plugin's settings — is never evaluated: only an attribute that is text is interpolated,
|
|
79
|
+
and the page server reads attributes as saved. A provider's `input` also replaced the route param of the same name
|
|
80
|
+
the action was already given, so `input: { room: '{{ navigation.routeParams.room }}' }` reached the task as `""` and
|
|
81
|
+
the page answered 404; its refusal says the action is handed the page's route and query params already. Anything
|
|
82
|
+
else is a binding on the attribute. `mockData`, a sample, is not held to it.
|
|
83
|
+
- **Rules on top of a class need no `id`** (`class: [card, { gap: '6px' }]`): they are named after the id the element
|
|
84
|
+
is given, written or not. `modifier-without-id` is gone; a one-off tweak no longer needs a name nothing reads.
|
|
85
|
+
- **Typed list rows have `inTemplate`**, as untyped ones do, and `bindTemplate`, `visibleWhen`, `hiddenWhen` and
|
|
86
|
+
`variantFrom` take a typed source's path as well as a name: turning a list typed broke every template of its rows.
|
|
87
|
+
- **`when({ field, operator: 'empty' })`** takes no `value` (nor `notEmpty`), as flows.md recommends; it did not
|
|
88
|
+
type-check.
|
|
89
|
+
- **Data-driven colours**: a style binding on a custom property (`{ to: '--who', category: 'style' }`) is written as
|
|
90
|
+
named — it was camel-cased into `who` — so a class reads `var(--who, var(--muted))`. A style binding's value carrying
|
|
91
|
+
`;` or braces is not written: the page server writes inline styles as text, and such a value added declarations of
|
|
92
|
+
its own. `binding-target-unknown` on `style` or a CSS property says to bind it in the `style` category.
|
|
93
|
+
- `unknown-attribute` for `decorative` on an `svg` or a `fontAwesome` says what it means: without a `label` it is
|
|
94
|
+
already hidden from screen readers.
|
|
95
|
+
|
|
96
|
+
- **A folder nobody declared says where to declare it**: `folder-undeclared` (a page, a layout, a folder's parent)
|
|
97
|
+
ends with `pageFolders: [{ id, name }]` on the space, and with the line of the `pageFamily` that wrote the page. A
|
|
98
|
+
folder starts its pages' addresses (`/docs/quickstart`), so a misspelt one is never declared on the author's behalf.
|
|
99
|
+
The skill's `pageFamily` example declares its folder.
|
|
100
|
+
- **A tag is an element**: a `subType` this element has not but another has — `container({ subType: 'ol' })` — names
|
|
101
|
+
that element (`list({ subType: 'ol' })`) instead of the value two letters away (`dl`). Read off the elements'
|
|
102
|
+
declarations, for every element and tag.
|
|
103
|
+
- **A `pageFamily`'s body is written once**: `repeated-shape` and `repeated-on-pages` no longer count the same part of
|
|
104
|
+
each page of one family as copies — they were offering a component for exactly what the docs recommend. Copies within
|
|
105
|
+
one page, or across pages written one by one, are still offered.
|
|
106
|
+
- **Colour emoji are not text to `page check`**: a character painted in its own colours (🎲, `❤️`, a keycap, a ZWJ
|
|
107
|
+
sequence) is left out of the contrast measure, which compared `color` with the tile behind it and failed `verify`
|
|
108
|
+
in the theme whose text colour was close to the tile. A symbol drawn as text (✓, ★) is still measured.
|
|
109
|
+
|
|
110
|
+
- **`declared-callback-target`** (refused): a value beside `on` in `declaredCallback(…, { on, date })` — written as
|
|
111
|
+
`openModal`'s target reads — was read nowhere, and the step ran without it. Refused, with the `params` it goes in
|
|
112
|
+
(`{ on: 'calendar', params: { date } }`) and whether it is one of the callback's declared params.
|
|
113
|
+
- The skill's list rows show the typed form beside the untyped one: with `items` typed by a sample, `r.item` is a path
|
|
114
|
+
(`from: r.item.title`), not text to put in a template string.
|
|
115
|
+
- **`slot-not-class`** (refused): rules written in place in a slot — `slots: { error: [fieldError, { color }] }`, past
|
|
116
|
+
the type in JavaScript or a spec rebuilt from JSON — were taken for a declaration with no rules, and `authorSpace`
|
|
117
|
+
failed later with `Cannot read properties of undefined (reading 'desktop')`, naming nothing. Refused where the slot
|
|
118
|
+
is written, naming the slot and the element, with the `styles()` declaration to hand instead.
|
|
119
|
+
|
|
120
|
+
## CLI
|
|
121
|
+
- **`page shot --click` (and `--clip`, `--wait-for`, `--scroll-to`, `--steps`) takes any selector**: a value that is
|
|
122
|
+
not an element's name (letters, digits, `-`, `_`) is a selector, CSS or Playwright's own (`button:has-text("Orbit")`).
|
|
123
|
+
It was wrapped as a name, and an invalid selector ended the command with Playwright's stack trace; it is now refused
|
|
124
|
+
with the reason.
|
|
125
|
+
|
|
126
|
+
- **`plitzi functions add <package>`**: a package the functions use comes with them, as a function carries its
|
|
127
|
+
dependencies. Installed in the project, it is bundled (web APIs only, minified, its licence kept) into
|
|
128
|
+
`src/functions/vendor/<package>.js`, with a `.d.ts` re-exporting the installed package's types, imported as
|
|
129
|
+
`./vendor/<package>.js` and pushed, built and run with the rest — nothing is resolved anywhere else, so the builder,
|
|
130
|
+
the sandbox and the push are unchanged. A package that reaches Node (`fs`, `node:*`) is refused, naming what it
|
|
131
|
+
reached; one past the functions' 1 MB is too; one that reads `process`/`Buffer` is warned about. The build's refusal
|
|
132
|
+
of a package import now names the command.
|
|
133
|
+
- **`page shot` targets**: a bare word is an element's name, or — no element named so — a tag (`textarea`); resolved on
|
|
134
|
+
the loaded page for `--click`, `--clip`, `--scroll-to`, `--wait-for` and `--steps`. In `--steps`, `type` takes a
|
|
135
|
+
quoted element with spaces (`type ".panel textarea" hola`) — it was cut at its first space and typed the rest — and
|
|
136
|
+
fails when the click leaves no field focused, rather than sending the keys to the page's shortcuts.
|
|
137
|
+
|
|
138
|
+
## Server
|
|
139
|
+
- **`server.listen()` resolves once the port answers** (`@plitzi/sdk-server`) — in a fleet, once the first worker
|
|
140
|
+
does. `serveProject` writes `tmp/dev-server.json` and says `pages on …` after it, not on the line after `listen`:
|
|
141
|
+
for about 0.4 s a tool trusting the line (CI, Playwright's `webServer`, `page check`) was refused. A port it cannot
|
|
142
|
+
take still ends the process, or goes to `onListenError`, and the promise is then never resolved.
|
|
143
|
+
- **Runs set for later** (`@plitzi/sdk-server`, `@plitzi/sdk-shared`, `@plitzi/sdk-authoring`, `@plitzi/plitzi-builder`):
|
|
144
|
+
a turn that runs out, a bot's move, a hold that lapses — one run starting one of the space's actions in N seconds,
|
|
145
|
+
whether or not a page is still open. The action says it may be with a **`later` trigger** (no access rule: the run
|
|
146
|
+
that set it was let in); a flow sets it with `flow.later { action, in, input, key }`, a function with
|
|
147
|
+
`ctx.later({ … })`, and `flow.cancelLater` / `ctx.cancelLater(key)` drops it. A `key` names it: set again under the
|
|
148
|
+
same key, the one still waiting is replaced — the newer of two set at once, on every replica — and a running one is
|
|
149
|
+
left. It is a job of the queue schedules use: due by the store's clock (0 s to 30 days, about a second late at most),
|
|
150
|
+
once across replicas, retried, shown in Automations → Queue. Refused before anything is queued, with why: no `later`
|
|
151
|
+
trigger, one switched off, a time out of range, a key that is not one, a server with no jobs. A plugin's functions
|
|
152
|
+
set none. `ActionJobQueue` gains `cancelPending({ spaceId, key, olderThan? })` and jobs a `key`: the memory, Mongo
|
|
153
|
+
and MySQL queues implement it, and the shared contract tests it. **MySQL**: `action_jobs` gains `job_key` (and the
|
|
154
|
+
`action_jobs_key` index), added on first use; with `createTables: false`, run that statement of
|
|
155
|
+
`mysqlJobSchemaUpgrades()`. A queue of a deployment's own implements `cancelPending` (`09-schedules` shows one).
|
|
156
|
+
- **A project's `kv` file has one holder** (`@plitzi/sdk-server`): `createFileKv` takes `<file>.lock` with its pid;
|
|
157
|
+
a second process — another `npm start`, a `--watch` left running — is refused, naming the first (`the server of
|
|
158
|
+
"orbita", on port 8080`) instead of both writing their whole map over each other's changes, and a lock whose process
|
|
159
|
+
is gone is taken over. `close()` writes what is pending and lets go. A server with `workers` opens the file once, in
|
|
160
|
+
the primary, and its workers reach it through the fleet (`fleetKv`): each used to open a copy of its own.
|
|
161
|
+
- **A self-hosted project's credentials** (`@plitzi/sdk-server`, `@plitzi/cli`): `serveProject` answers
|
|
162
|
+
`getCredential` from `PLITZI_CREDENTIALS` in `.env` — one JSON object, credential id → its keys — so
|
|
163
|
+
`ctx.fetch({ credential })`, a connector and an `http.request` step work on the project's own server, not only in
|
|
164
|
+
`functions dev`. The same variable for both (it was `PLITZI_FUNCTIONS_CREDENTIALS`, read by the CLI alone); a value
|
|
165
|
+
that is not that object is refused with how to write it, instead of every credential going missing.
|
|
166
|
+
- **`HOST` beyond loopback says where to open it**: with `HOST=0.0.0.0`, `serveProject` prints the machine's network
|
|
167
|
+
addresses — what a tablet on the same Wi-Fi opens — and that anyone on that network can. `.env.example` names `HOST`
|
|
168
|
+
and `PLITZI_CREDENTIALS`.
|
|
169
|
+
|
|
170
|
+
## SDK
|
|
171
|
+
- **`useElementSize(ref)`** (`@plitzi/plitzi-sdk`): the size a plugin's own box is drawn at, followed as it changes —
|
|
172
|
+
what `useDisplayMode()` cannot say: a tablet held upright is `mobile` by the window and still a week wide by the
|
|
173
|
+
plugin's box. `undefined` until measured, so the server's page and the hydrated one agree. The breakpoints are
|
|
174
|
+
unchanged.
|
|
175
|
+
- The functions docs say how a task's `params` types (how the builder edits them: `codemirror-json`) and an action's
|
|
176
|
+
`input` types (what the value is: `json`) correspond.
|
|
177
|
+
|
|
178
|
+
## 0.38.10
|
|
179
|
+
|
|
180
|
+
### Patch Changes
|
|
181
|
+
|
|
182
|
+
- 200da2f: - **`focus-on-field-box`** (`@plitzi/sdk-authoring`): a warning for a `focus` or `focus-visible` state on a text
|
|
183
|
+
field's or a select's `input` slot. That slot is the box the field is drawn in, a `<div>` that never takes focus, so
|
|
184
|
+
the rule was never seen and a keyboard user tabbing to the field found no ring. The fix it names: `'focus-within'` on
|
|
185
|
+
the same class, or the state on the `field` slot.
|
|
186
|
+
- **`modalContainer` says how it is laid out** (`@plitzi/sdk-elements`): its description now names its slots and how
|
|
187
|
+
they sit — the dim layer and the dialog side by side, not one inside the other; the dialog centred by `top`/`left`
|
|
188
|
+
50% and a `translate`. A space styled the dim layer as a flex container to place the dialog, which moved nothing.
|
|
189
|
+
- **A field shows where the keyboard is** (`@plitzi/plitzi-sdk`, `@plitzi/sdk-elements`): a text field's or a select's
|
|
190
|
+
box is ringed (`2px solid currentColor`) while the field inside has keyboard focus, and a textarea while it has. No
|
|
191
|
+
text field or select showed any focus at all: the box had `outline: none`, and the field inherited it. One class of
|
|
192
|
+
specificity, so whatever a space writes about the outline wins; never in the builder's canvas, where the selection is
|
|
193
|
+
the ring. The field no longer inherits the box's outline — the box draws it.
|
|
194
|
+
- **The dim layer of a modal and a dialog is `rgb(0 0 0 / 50%)`** (`@plitzi/plitzi-sdk`, `@plitzi/sdk-elements`), not
|
|
195
|
+
black at `opacity: 0.5`: the default looks the same, and a colour a space gives the layer is drawn as it is — it was
|
|
196
|
+
halved. A space that set its own colour sees it darker: the one it wrote.
|
|
197
|
+
- **`required-message-unused`** (`@plitzi/sdk-authoring`): a warning for a `requiredMessage` on a field nothing requires —
|
|
198
|
+
since 0.38.9 a field is optional unless `required: true`, so the message is never shown and an empty answer is sent.
|
|
199
|
+
The formControl's description, the cheat sheet and the forms recipe say the default.
|
|
200
|
+
- **A page's title can say its record** (`@plitzi/sdk-shared`, `@plitzi/sdk-server`, `@plitzi/sdk-elements`,
|
|
201
|
+
`@plitzi/sdk-authoring`): `seoTitle` and `seoDescription` may be templates over the page's `runtime: 'server'`
|
|
202
|
+
providers (its layouts' too) and `navigation` — `'{{ apiContainer_post.title }} — Blog'`. The server evaluates them
|
|
203
|
+
as it writes the head, from the answers it already has; the browser evaluates the same over `rsc.data`, so the tab
|
|
204
|
+
follows a navigation from record to record. One that reads anything else — a browser provider, `state` — is refused
|
|
205
|
+
(`page-template`): it was written into the head as it was, braces included. A declaration's `serverTemplates` names
|
|
206
|
+
the attributes the page server evaluates against a context of its own (a page's title and description, a provider's
|
|
207
|
+
`notFound`): the element runtime leaves them as written — interpolated where the page renders, a `|default(…)`
|
|
208
|
+
resolved to its fallback before the head could read the providers — and the authoring lint reads the same list.
|
|
209
|
+
- **A page says when its address shows nothing** (`@plitzi/sdk-server`, `@plitzi/sdk-authoring`): `notFound` on the
|
|
210
|
+
page, one expression over the same answers its title reads — `"{{ not (apiContainer_feed.topics|find('slug',
|
|
211
|
+
navigation.routeParams.slug)) }}"` — sends it with status 404, rendered as written. A provider's own `notFound` reads
|
|
212
|
+
only its answer, and one in a layout is every page's: a record read from the layout had no way to say it was not
|
|
213
|
+
there, and the page answered 200.
|
|
214
|
+
- **The Export keeps the flows of a plugin hosted by `custom`** (`@plitzi/sdk-authoring`): `specFromSpace` judged such
|
|
215
|
+
an element by `custom`'s own triggers and callbacks, and dropped a flow on the component's event (`onChange` on an
|
|
216
|
+
editor) as one "a custom never fires" — the space read back was not the space written.
|
|
217
|
+
- **`page check` reads every word on the page, in the colour the browser paints it** (`@plitzi/sdk-authoring`): what a
|
|
218
|
+
plugin draws inside an element of the space is measured too, named by the element and a selector; the measure is
|
|
219
|
+
WCAG's contrast (under 2:1 is unreadable), not "nearly the same colour"; and a colour the browser answers as
|
|
220
|
+
`oklch()`, `oklab()` or `color(srgb …)` — every token and every `color-mix()` — is read as that, where it was read as
|
|
221
|
+
`rgb()` numbers and came out near black. A plugin's dark-on-dark status line passed as "nothing wrong".
|
|
222
|
+
- **`verify` checks every theme the space can be painted in** (`@plitzi/cli`): light and dark, unless the space says
|
|
223
|
+
light only — "48 checks at 1440 and 390 px, light and dark". A page unreadable in the dark theme passed in the light
|
|
224
|
+
one; a failure names the theme it was found in.
|
|
225
|
+
- **`plitzi upgrade` says where fields became optional** (`@plitzi/cli`): for a project last upgraded before 0.38.9,
|
|
226
|
+
each `formControl(…)` with no `required`, at its file and line — said, never written. And a `.gitkeep` is asked for
|
|
227
|
+
only in a folder with nothing else in it: `upgrade` wrote one beside code, and `doctor` called it missing once deleted
|
|
228
|
+
as AGENTS.md asks ("nothing unused") — the three now say the same.
|
|
229
|
+
- **`devMode` and `devReload` are the project's** (`@plitzi/sdk-server`): `src/config/serverOptions.ts` may set them,
|
|
230
|
+
over `NODE_ENV`, which they still follow when left out. A deployment started without `NODE_ENV` (a container's `CMD`)
|
|
231
|
+
says `devMode: false`, and a public action answers with its output alone.
|
|
232
|
+
- **`page shot --from load`** (`@plitzi/cli`): `--frames` start as soon as the page's HTML is in, not once it settles —
|
|
233
|
+
an entrance that plays while the page loads had ended before the first picture.
|
|
234
|
+
- **`heavy-animation` says where each animation is** (`@plitzi/sdk-authoring`): the class and its variant, state or
|
|
235
|
+
slot — or the `customCss` rule — and writes the fix against that selector. It said "in `customCss`" for an animation
|
|
236
|
+
declared on a class's variant, and offered `.glow`, a class no space has.
|
|
237
|
+
- **`page shot --steps`** (`@plitzi/cli`): an interaction played step by step — `click`, `type`, `press`, `wait`,
|
|
238
|
+
`wait-for`, `shot [label]`, `frames <n> [ms]`, separated by `;` or written in a file (`@file`) — each picture labelled
|
|
239
|
+
with its step and the time since the first, and said when nothing changed since the one before. A queue filling, a
|
|
240
|
+
restart, an opening frame by frame took a Playwright script of the project's own. Targets take Playwright's selectors
|
|
241
|
+
too (`text=Saved`).
|
|
242
|
+
- **A space's task may take a `number` param** (`@plitzi/sdk-server`): saved functions refused it ("a type the builder
|
|
243
|
+
cannot draw") while a project's server ran it, so code that worked self-hosted failed on the platform — and the
|
|
244
|
+
builder draws one, a callback's. A step's params now arrive as the types the task declares, on every server: a
|
|
245
|
+
`number` written as text is the number, a `boolean` written `'true'` is `true`, as the browser reads a callback's.
|
|
246
|
+
- **`page shot --as <username>`** (`@plitzi/cli`): signs in first, as `page check --as` does, the password from
|
|
247
|
+
`PLITZI_CHECK_PASSWORD` in `.env`. A page for signed-in visitors was pictured as the sign-in page it sent the browser
|
|
248
|
+
to, without a word; `page shot` now says when the page sent it elsewhere, and that the picture is of that page.
|
|
249
|
+
- **A capture is of the page at rest** (`@plitzi/sdk-mcp`): the local screenshot client takes every picture with
|
|
250
|
+
`prefers-reduced-motion: reduce`, as the browser pod now does — the declared motion and a space's own keyframes that
|
|
251
|
+
honour the query are shown finished. A splash still covering its page, or an arrival caught halfway, was what a
|
|
252
|
+
thumbnail or a `plitzi_look` showed of a page that animates as it loads.
|
|
253
|
+
- **The server renders in the visitor's theme, not only the class** (`@plitzi/sdk-shared`): `ThemeProvider` set the
|
|
254
|
+
starting theme from a layout effect, which never runs on a server, so a page was drawn from the theme store's own
|
|
255
|
+
start — `{{ theme.resolved }}` was `light` under a `<html class="dark">`, and whatever named the scheme (a picture's
|
|
256
|
+
address, a `when` rule) was swapped for the other one as the page hydrated. The theme a host supplies (the cookie) is
|
|
257
|
+
now the server's snapshot of the store, and the hydration's; the shared store is never written on the server.
|
|
258
|
+
|
|
3
259
|
## 0.38.9
|
|
4
260
|
|
|
5
261
|
### Patch Changes
|
|
@@ -18,6 +18,7 @@ var s = [
|
|
|
18
18
|
"call",
|
|
19
19
|
"webhook",
|
|
20
20
|
"schedule",
|
|
21
|
+
"later",
|
|
21
22
|
"render",
|
|
22
23
|
"custom"
|
|
23
24
|
], u = ["sha256", "sha1"], d = /* @__PURE__ */ new Set([
|
|
@@ -78,7 +79,7 @@ var s = [
|
|
|
78
79
|
message: "is not valid JSON"
|
|
79
80
|
}) : h(e, `${g}.params.input`, d);
|
|
80
81
|
}
|
|
81
|
-
if (_ !== "schedule") {
|
|
82
|
+
if (_ !== "schedule" && _ !== "later") {
|
|
82
83
|
if (!p(v.access) || !c.includes(v.access)) d.push({
|
|
83
84
|
path: `${g}.params.access`,
|
|
84
85
|
message: "must say who may start a run this way",
|
|
@@ -67,6 +67,14 @@ export interface ElementDeclarationData {
|
|
|
67
67
|
* `plitzi page check`), which would otherwise wait for it to be on screen and report it hidden.
|
|
68
68
|
*/
|
|
69
69
|
drawsNothing?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* The attributes the page server evaluates against a context of its own, never where the element renders: a
|
|
72
|
+
* provider's `notFound`, read against its answer; a page's title and description, read against its server providers.
|
|
73
|
+
* Interpolated in the element's own scope they resolved to nothing — a `|default(…)` to its fallback — before the
|
|
74
|
+
* reader that has their names could see them. Read by the element runtime, which leaves them as written, and by the
|
|
75
|
+
* authoring lint, which holds them to that context.
|
|
76
|
+
*/
|
|
77
|
+
serverTemplates?: readonly string[];
|
|
70
78
|
content?: {
|
|
71
79
|
attributes?: Record<string, unknown>;
|
|
72
80
|
definition?: {
|
|
@@ -11,35 +11,35 @@ var c = (e, t, n, r, a) => {
|
|
|
11
11
|
fromValue: t ? i(e, t) : void 0,
|
|
12
12
|
toValue: i(n, o, t ? i(e, t) : void 0)
|
|
13
13
|
};
|
|
14
|
-
}, l = (
|
|
15
|
-
let { attributes:
|
|
16
|
-
return !
|
|
17
|
-
attributes:
|
|
14
|
+
}, l = (e) => typeof e == "number" || typeof e == "string" && !/[;{}<>]/.test(e), u = (u, d, f = {}) => {
|
|
15
|
+
let { attributes: p, definition: m } = d, { bindings: h } = m;
|
|
16
|
+
return !h || typeof h == "object" && !Object.keys(h).length ? {
|
|
17
|
+
attributes: p,
|
|
18
18
|
style: {},
|
|
19
|
-
definition:
|
|
19
|
+
definition: m
|
|
20
20
|
} : s({
|
|
21
|
-
attributes:
|
|
22
|
-
style:
|
|
23
|
-
definition:
|
|
21
|
+
attributes: p,
|
|
22
|
+
style: f,
|
|
23
|
+
definition: m
|
|
24
24
|
}, (s) => {
|
|
25
|
-
Object.keys(
|
|
26
|
-
|
|
27
|
-
let { source:
|
|
28
|
-
if (!
|
|
29
|
-
|
|
30
|
-
let { fromValue:
|
|
31
|
-
|
|
25
|
+
Object.keys(h).forEach((d) => {
|
|
26
|
+
h[d] && Array.isArray(h[d]) && h[d].length && h[d].forEach((f) => {
|
|
27
|
+
let { source: p, transformers: m, when: h, enabled: g = !0 } = f, { to: _ } = f;
|
|
28
|
+
if (!_ || h && !o(h, u, !1, !0) || !g) return;
|
|
29
|
+
d === "style" && !_.startsWith("--") && (_ = r(_));
|
|
30
|
+
let { fromValue: v, toValue: y } = c(u, p, s, d, _), b = v;
|
|
31
|
+
m && Array.isArray(m) && m.length > 0 && m.forEach((e) => {
|
|
32
32
|
let { action: r, params: i, enabled: a = !0 } = e;
|
|
33
33
|
if (!a) return;
|
|
34
34
|
let o = t[r];
|
|
35
|
-
o && (
|
|
36
|
-
...
|
|
37
|
-
sourceTo:
|
|
35
|
+
o && (b = o.callback(b, n(o, i) ?? {}, s, {
|
|
36
|
+
...u,
|
|
37
|
+
sourceTo: y
|
|
38
38
|
}));
|
|
39
|
-
}),
|
|
39
|
+
}), d === "initialState" && _ === "visibility" && p && i(u, p) !== void 0 && (b = e(b)), (d !== "style" || l(b)) && (typeof b == "boolean" || typeof b == "number" || b) && (d === "initialState" ? a(s, `definition.${d}.${_}`, b) : a(s, `${d}.${_}`, b));
|
|
40
40
|
});
|
|
41
41
|
});
|
|
42
42
|
});
|
|
43
43
|
};
|
|
44
44
|
//#endregion
|
|
45
|
-
export {
|
|
45
|
+
export { u as default };
|
package/dist/index.mjs
CHANGED
|
@@ -70,27 +70,27 @@ import jn from "./schema/SchemaContext.mjs";
|
|
|
70
70
|
import { ANCHOR_PATTERN as Mn, anchorOf as Nn, isAnchor as Pn, uniqueAnchor as Fn } from "./schema/anchor.mjs";
|
|
71
71
|
import { COMPONENT_PROPS_SOURCE as In, EMPTY_SCHEMA as Ln, VARIABLE_REGEX as Rn } from "./schema/schemaConstants.mjs";
|
|
72
72
|
import { findLayoutCycle as zn, resolveLayoutChain as Bn } from "./schema/layoutChain.mjs";
|
|
73
|
-
import { collectServerElements as Vn, hasServerElements as Hn, notFoundProvider as Un } from "./schema/serverElements.mjs";
|
|
74
|
-
import { isSnippet as
|
|
75
|
-
import
|
|
76
|
-
import
|
|
77
|
-
import { elementFromWire as
|
|
78
|
-
import { SpaceEvents as
|
|
79
|
-
import
|
|
80
|
-
import
|
|
81
|
-
import
|
|
82
|
-
import
|
|
83
|
-
import
|
|
84
|
-
import
|
|
85
|
-
import { THEME_CLASSES as
|
|
86
|
-
import
|
|
87
|
-
import { useThemeStore as
|
|
88
|
-
import
|
|
89
|
-
import
|
|
90
|
-
import
|
|
91
|
-
import
|
|
92
|
-
import
|
|
93
|
-
import
|
|
94
|
-
import { PAINTED_STATE_BUDGET as
|
|
95
|
-
import { runtimeStatePersist as
|
|
96
|
-
export { Mn as ANCHOR_PATTERN, x as BODYLESS_METHODS, y as BuilderContext,
|
|
73
|
+
import { collectServerElements as Vn, hasServerElements as Hn, notFoundProvider as Un, pageNotFound as Wn, pageSeoText as Gn, pageServerContext as Kn } from "./schema/serverElements.mjs";
|
|
74
|
+
import { isSnippet as qn } from "./schema/snippet.mjs";
|
|
75
|
+
import Jn from "./network/NetworkContext.mjs";
|
|
76
|
+
import Yn from "./network/NetworkInternalContext.mjs";
|
|
77
|
+
import { elementFromWire as Xn, schemaFromWire as Zn, schemaToWire as Qn } from "./schema/wire.mjs";
|
|
78
|
+
import { SpaceEvents as $n, spaceEventSchemas as er, validateSpaceEvent as tr } from "./network/spaceEvents.mjs";
|
|
79
|
+
import nr from "./network/graphql/builder/Mutations/index.mjs";
|
|
80
|
+
import rr from "./network/graphql/builder/Queries/index.mjs";
|
|
81
|
+
import ir from "./network/graphql/builder/Subscriptions/index.mjs";
|
|
82
|
+
import ar from "./network/graphql/sdk/Mutations/index.mjs";
|
|
83
|
+
import or from "./network/graphql/sdk/Queries/index.mjs";
|
|
84
|
+
import sr, { RTEvent as cr, RTEventCloseCode as lr, getInstance as ur, isRTEvent as dr, isRTEventCloseCode as fr, setInstance as pr } from "./websockets/RTCodec.mjs";
|
|
85
|
+
import { THEME_CLASSES as mr, THEME_COOKIE_NAME as hr, applyThemeClass as gr, isTheme as _r, readThemeCookie as vr, themeFromCookies as yr, writeThemeCookie as br } from "./theme/themeCookie.mjs";
|
|
86
|
+
import xr, { createThemeState as Sr, createThemeStore as Cr, resolveScheme as wr, setAreaTheme as Tr, setMachineScheme as Er, setThemeMode as Dr, startingThemeState as Or, themeFor as kr } from "./theme/themeStore.mjs";
|
|
87
|
+
import { ThemeStartContext as Ar, useThemeState as jr, useThemeStore as Mr } from "./theme/ThemeScope.mjs";
|
|
88
|
+
import Nr from "./theme/ThemeProvider.mjs";
|
|
89
|
+
import Pr, { SPACE_THEME_AREA as Fr } from "./theme/useTheme.mjs";
|
|
90
|
+
import Ir from "./server/actions/useActionsSync.mjs";
|
|
91
|
+
import Lr, { cancelRsc as Rr, currentRscLocation as zr, releaseRscRequests as Br, rscDataPath as Vr } from "./server/rsc/refreshRsc.mjs";
|
|
92
|
+
import Hr from "./server/rsc/useRscRefresh.mjs";
|
|
93
|
+
import Ur from "./server/rsc/useRscSync.mjs";
|
|
94
|
+
import { PAINTED_STATE_BUDGET as Wr, clearPaintedEntry as Gr, paintedEntryFromCookies as Kr, paintedKeys as qr, paintedStateCookieName as Jr, paintedStateFor as Yr, pickPainted as Xr, readPaintedEntry as Zr, writePaintedEntry as Qr } from "./state/paintedState.mjs";
|
|
95
|
+
import { runtimeStatePersist as $r, stateOwner as ei } from "./state/runtimeStatePersist.mjs";
|
|
96
|
+
export { Mn as ANCHOR_PATTERN, x as BODYLESS_METHODS, y as BuilderContext, nr as BuilderMutations, rr as BuilderQueries, In as COMPONENT_PROPS_SOURCE, N as COMPUTED_GLOBALS, S as CONNECTOR_HTTP_METHODS, an as CONTENT_PSEUDOS, mn as CURRENT_SELECTOR, Me as ComponentContext, C as DEFAULT_READ_ENDPOINT, Te as DEV_TOOLS_ATTRIBUTE, St as DISPLAY_MODES, gt as DISPLAY_MODE_MIN_WIDTH, we as DevToolsContext, w as EMPTY_RESPONSE_METHODS, Ln as EMPTY_SCHEMA, ft as EMPTY_STYLE_SCHEMA, hn as EXPANDED_SELECTOR, Ne as FLAG_GATE_PATTERN, Ue as FLAG_LAYERS, Pe as FLAG_NAME_PATTERN, Ft as FontValidationError, on as GENERATED_PSEUDOS, P as GLOBAL_SOURCES, gn as HIDDEN_CLASS, Ee as HIDE_DEV_TOOLS_CSS, ee as INTERVAL_TRIGGER, zt as LAYOUT_GRIDS, m as MAX_PARAM_PASSES, te as MIN_INTERVAL_MS, Yt as MOTION_CONDITIONS, Jn as NetworkContext, Yn as NetworkInternalContext, Wr as PAINTED_STATE_BUDGET, _n as PARENT_ANCESTOR, yt as PLUGIN_CSS_LAYER, sn as PSEUDO_PROPERTIES, oe as ParamsFromURL, ke as PlitziConsole, ot as PlitziServiceContext, st as PlitziServiceProvider, T as READ_ENDPOINT_NAMES, sr as RTCodec, cr as RTEvent, lr as RTEventCloseCode, bt as RUNTIME_CSS_LAYER, Ht as RUNTIME_STYLE_ID, Fr as SPACE_THEME_AREA, Xt as STYLE_CONDITION_LABELS, Zt as STYLE_MOTION_CONDITIONS, cn as STYLE_PSEUDOS, ln as STYLE_PSEUDO_LABELS, vn as STYLE_STATES, yn as STYLE_STATE_LABELS, Tt as SYSTEM_FONTS, jn as SchemaContext, ar as SdkMutations, or as SdkQueries, ir as SpaceEventSubscription, $n as SpaceEvents, pt as StyleBindingsAllowed, lt as StyleVariableCategory, mr as THEME_CLASSES, hr as THEME_COOKIE_NAME, Nr as ThemeProvider, Ar as ThemeStartContext, Rn as VARIABLE_REGEX, a as VISITOR_NAME, ct as WHILE_RUNNING_MODES, E as WRITE_ENDPOINT_NAMES, Nn as anchorOf, gr as applyThemeClass, t as authFailureFromResponse, Et as availableFonts, mt as baseDefaultValue, Rr as cancelRsc, Qt as canonicalCondition, o as checkVisitorRoles, Gr as clearPaintedEntry, Vn as collectServerElements, $t as conditionAtRule, en as conditionLabel, tn as conditionOfAtRule, k as connectorPresets, D as connectorTokens, b as contexts, B as cookieFromHeader, Ae as createStoreDevToolsLogger, Sr as createThemeState, Cr as createThemeStore, zr as currentRscLocation, De as debugCookieName, se as delay, Xe as describeChange, $e as diffSchema, et as diffStyle, he as disableReactDevTools, _t as displayModeAt, vt as displayModeWidthRem, V as documentCookies, Xn as elementFromWire, H as elementOf, A as emptyManifest, ce as emptyObject, F as evaluateComputed, ae as evaluateRuleGroup, Lt as fallbackForFamily, Dt as familiesInCss, L as fetchManifest, Ze as fieldChanges, c as filters, zn as findLayoutCycle, We as flagUserFromSSR, Ge as flagValues, Le as flagsCookieName, Ot as fontFamilyStack, wt as fontLinkAssets, kt as fontUrlResolver, Rt as fontsFromCss, At as fontsToHead, Re as forcedFlagsFromCookies, K as formatDate, q as formatDateUTC, J as formatFromNow, Y as formatUTCToLocal, R as generateFacade, ve as getBindingsDetails, O as getConnectorTokens, le as getDisplayName, X as getDurationMs, ur as getInstance, ue as getKeyDecoded, de as getPathsFromObeject, ye as getSourceName, jt as googleCss2Url, Mt as googleTextSubsetUrl, Ke as hasConditions, Hn as hasServerElements, f as hasTemplateSyntax, p as hasValidToken, fe as hexToRGB, bn as inCascadeOrder, xt as inPluginLayer, ht as inheritableAttributesBase, g as inspectTemplate, ne as intervalOf, Pn as isAnchor, j as isConnectorManifestDraft, un as isContentValue, re as isDate, Ct as isDisplayMode, U as isElementTarget, Fe as isFlagName, pe as isInViewport, Oe as isInteractionFlow, xn as isKnownState, W as isNodeTarget, Sn as isParentAncestor, dr as isRTEvent, fr as isRTEventCloseCode, e as isRecord, Nt as isSafeFontUrl, Ie as isSchemaFlag, qn as isSnippet, Cn as isStartingState, nn as isStyleCondition, dn as isStylePseudo, Tn as isStyleRules, ut as isStyleVariableCategory, _r as isTheme, ie as isUserEdit, Z as isValidFormat, tt as jsonCopy, Bt as layoutGridCss, Vt as layoutGridLook, I as liveSources, me as makeId, Ut as markStyleCache, Kt as mergeSnippetStyle, G as nodeOf, Un as notFoundProvider, n as onAuthFailure, je as pConsole, Wn as pageNotFound, Gn as pageSeoText, Kn as pageServerContext, Kr as paintedEntryFromCookies, qr as paintedKeys, Jr as paintedStateCookieName, Yr as paintedStateFor, rn as parseContainerCondition, Q as parseDate, ze as parseFlagList, It as parseSpaceFont, qe as passesFlagGate, Xr as pickPainted, Pt as primaryFamily, l as processTwig, u as processTwigParam, d as processTwigValue, fn as pseudoHonours, pn as pseudoSuffix, Zr as readPaintedEntry, vr as readThemeCookie, Lr as refreshRsc, Br as releaseRscRequests, r as reportAuthFailure, Je as resolveFlags, Bn as resolveLayoutChain, wr as resolveScheme, h as resolveStepParam, Se as resolveVariables, Vr as rscDataPath, $r as runtimeStatePersist, i as sameRegistrableDomain, qt as sameSelector, nt as sameValue, Zn as schemaFromWire, Qn as schemaToWire, Jt as selectorsOf, Be as serializeFlagList, Tr as setAreaTheme, En as setAtKeys, pr as setInstance, Er as setMachineScheme, Dr as setThemeMode, er as spaceEventSchemas, Or as startingThemeState, ei as stateOwner, wn as stateSuffix, Wt as styleCacheFromDocument, Gt as styleCacheTravelsInDocument, dt as styleConstants, Dn as styleTargetKeys, On as styleTargetProblem, kn as styleTargetRules, z as syntaxHighlight, _ as templatePaths, v as templateRootNames, kr as themeFor, yr as themeFromCookies, xr as themeStore, $ as toUnixSeconds, Ye as undeclaredFlagOverrides, Fn as uniqueAnchor, Qe as uniqueLines, Ir as useActionsSync, rt as useFontHead, it as useNetwork, at as usePlitziServiceContext, be as useRegisterSource, Ce as useResolvedVariables, Hr as useRscRefresh, Ur as useRscSync, xe as useStableValue, Pr as useTheme, jr as useThemeState, Mr as useThemeStore, ge as utility, _e as utilityOptions, M as validateConnectorManifest, tr as validateSpaceEvent, An as valueAtKeys, s as visitorAccess, Ve as withForcedFlag, He as writeForcedFlags, Qr as writePaintedEntry, br as writeThemeCookie };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RealtimeMessage, RealtimeTransport } from '../types/RealtimeTypes';
|
|
1
|
+
import { RealtimeMessage, RealtimePublishOptions, RealtimeTransport } from '../types/RealtimeTypes';
|
|
2
2
|
export type RealtimeStatus = 'idle' | 'connecting' | 'open' | 'closed';
|
|
3
3
|
type MessageListener = (message: RealtimeMessage) => void;
|
|
4
4
|
type StatusListener = (status: RealtimeStatus) => void;
|
|
@@ -11,8 +11,11 @@ export type RealtimeClient = {
|
|
|
11
11
|
* reopens nothing the server already let in. `undefined` forgets it.
|
|
12
12
|
*/
|
|
13
13
|
grant: (topic: string, grant: string | undefined) => void;
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Sends on a topic this page listens to — heard by every other page on it, and by this one too with `echo`. `false`
|
|
16
|
+
* when the server refused it or there is no connection.
|
|
17
|
+
*/
|
|
18
|
+
publish: (topic: string, type: string, data: unknown, options?: RealtimePublishOptions) => Promise<boolean>;
|
|
16
19
|
onStatus: (listener: StatusListener) => () => void;
|
|
17
20
|
readonly status: RealtimeStatus;
|
|
18
21
|
/** This page's name on its channels — the `from` of what it sends — once connected. */
|
package/dist/realtime/client.mjs
CHANGED
|
@@ -67,9 +67,9 @@ var t = 30, n = [
|
|
|
67
67
|
topics: t,
|
|
68
68
|
transport: "sse",
|
|
69
69
|
close: () => r.abort(),
|
|
70
|
-
publish: async (t, n, r) => {
|
|
70
|
+
publish: async (t, n, r, { echo: i }) => {
|
|
71
71
|
if (!o) return !1;
|
|
72
|
-
let
|
|
72
|
+
let a = await f(e, {
|
|
73
73
|
method: "POST",
|
|
74
74
|
headers: { "content-type": "application/json" },
|
|
75
75
|
credentials: "same-origin",
|
|
@@ -77,10 +77,11 @@ var t = 30, n = [
|
|
|
77
77
|
token: o,
|
|
78
78
|
topic: t,
|
|
79
79
|
type: n,
|
|
80
|
-
data: r
|
|
80
|
+
data: r,
|
|
81
|
+
...i ? { echo: i } : {}
|
|
81
82
|
})
|
|
82
83
|
}).catch(() => void 0);
|
|
83
|
-
return
|
|
84
|
+
return a?.status === 401 && v === c && N(), a?.ok ?? !1;
|
|
84
85
|
}
|
|
85
86
|
}, l = async (e) => {
|
|
86
87
|
let t = e.body?.getReader();
|
|
@@ -119,22 +120,23 @@ var t = 30, n = [
|
|
|
119
120
|
close: () => {
|
|
120
121
|
m = !0, h(), s.close();
|
|
121
122
|
},
|
|
122
|
-
publish: (e, t, n) => new Promise((
|
|
123
|
+
publish: (e, t, n, { echo: i }) => new Promise((a) => {
|
|
123
124
|
if (s.readyState !== s.OPEN) {
|
|
124
|
-
|
|
125
|
+
a(!1);
|
|
125
126
|
return;
|
|
126
127
|
}
|
|
127
128
|
d += 1;
|
|
128
|
-
let
|
|
129
|
-
u.delete(
|
|
129
|
+
let o = d, c = setTimeout(() => {
|
|
130
|
+
u.delete(o), a(!1);
|
|
130
131
|
}, r);
|
|
131
|
-
u.set(
|
|
132
|
-
clearTimeout(
|
|
132
|
+
u.set(o, (e) => {
|
|
133
|
+
clearTimeout(c), a(e);
|
|
133
134
|
}), s.send(JSON.stringify({
|
|
134
|
-
id:
|
|
135
|
+
id: o,
|
|
135
136
|
topic: e,
|
|
136
137
|
type: t,
|
|
137
|
-
data: n
|
|
138
|
+
data: n,
|
|
139
|
+
...i ? { echo: i } : {}
|
|
138
140
|
}));
|
|
139
141
|
})
|
|
140
142
|
};
|
|
@@ -185,15 +187,15 @@ var t = 30, n = [
|
|
|
185
187
|
let n = F(e) && !y.has(e);
|
|
186
188
|
t && m.has(e) && !n && P(!0);
|
|
187
189
|
},
|
|
188
|
-
publish: async (e, t, n) => {
|
|
189
|
-
let
|
|
190
|
-
return d(
|
|
190
|
+
publish: async (e, t, n, r = {}) => {
|
|
191
|
+
let i = await I(e) && v ? await v.publish(e, t, n, r) : !1;
|
|
192
|
+
return d(i ? "info" : "danger", `${e} → ${t}${i ? "" : " (not delivered)"}`, {
|
|
191
193
|
event: "published",
|
|
192
194
|
topic: e,
|
|
193
195
|
type: t,
|
|
194
196
|
data: n,
|
|
195
|
-
delivered:
|
|
196
|
-
}),
|
|
197
|
+
delivered: i
|
|
198
|
+
}), i;
|
|
197
199
|
},
|
|
198
200
|
onStatus: (e) => (g.add(e), () => g.delete(e)),
|
|
199
201
|
get status() {
|
package/dist/realtime/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createRealtimeClient, realtimeClientFor } from './client';
|
|
2
2
|
export { trackPresence } from './presence';
|
|
3
|
-
export { JOIN_TYPE, LEAVE_TYPE, PRESENCE_TYPE, REVOKED_TYPE, channelLimits, channelProblems, isValidTopic, matchChannel } from './topics';
|
|
3
|
+
export { JOIN_TYPE, LEAVE_TYPE, OBSERVER_COOKIE_NAME, PRESENCE_TYPE, REVOKED_TYPE, channelLimits, channelProblems, isValidTopic, matchChannel } from './topics';
|
|
4
4
|
export type { RealtimeClient, RealtimeClientOptions, RealtimeStatus } from './client';
|
|
5
5
|
export type { PresenceListeners, PresenceTracker, RealtimeMember } from './presence';
|
|
6
6
|
export type { ChannelMatch } from './topics';
|
package/dist/realtime/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JOIN_TYPE as e, LEAVE_TYPE as t,
|
|
2
|
-
import { createRealtimeClient as
|
|
3
|
-
import { trackPresence as
|
|
4
|
-
export { e as JOIN_TYPE, t as LEAVE_TYPE, n as
|
|
1
|
+
import { JOIN_TYPE as e, LEAVE_TYPE as t, OBSERVER_COOKIE_NAME as n, PRESENCE_TYPE as r, REVOKED_TYPE as i, channelLimits as a, channelProblems as o, isValidTopic as s, matchChannel as c } from "./topics.mjs";
|
|
2
|
+
import { createRealtimeClient as l, realtimeClientFor as u } from "./client.mjs";
|
|
3
|
+
import { trackPresence as d } from "./presence.mjs";
|
|
4
|
+
export { e as JOIN_TYPE, t as LEAVE_TYPE, n as OBSERVER_COOKIE_NAME, r as PRESENCE_TYPE, i as REVOKED_TYPE, a as channelLimits, o as channelProblems, l as createRealtimeClient, s as isValidTopic, c as matchChannel, u as realtimeClientFor, d as trackPresence };
|
|
@@ -20,7 +20,7 @@ var t = 2e4, n = 65e3, r = /* @__PURE__ */ new WeakMap(), i = (r, i, a) => {
|
|
|
20
20
|
}, m = () => {
|
|
21
21
|
u && r.publish(i, e, l);
|
|
22
22
|
}, h = r.subscribe(i, (e) => {
|
|
23
|
-
if (e.from !== r.me) {
|
|
23
|
+
if (e.from !== r.me || e.echo === !0) {
|
|
24
24
|
if (e.type === "$presence") {
|
|
25
25
|
let t = {
|
|
26
26
|
from: e.from,
|
|
@@ -34,3 +34,9 @@ export declare const JOIN_TYPE = "$join";
|
|
|
34
34
|
* topic, and hears nothing more on it until a new grant opens it again.
|
|
35
35
|
*/
|
|
36
36
|
export declare const REVOKED_TYPE = "$revoked";
|
|
37
|
+
/**
|
|
38
|
+
* A page that watches its channels without taking part: what `plitzi page check` and `page shot` load pages with. It
|
|
39
|
+
* hears every topic it may open, and says nothing on any — no arrival, no presence, nothing it publishes — so a check
|
|
40
|
+
* of a live site is never a visitor walking into somebody's room. Anyone may set it; it silences only that page.
|
|
41
|
+
*/
|
|
42
|
+
export declare const OBSERVER_COOKIE_NAME = "plitzi-observer";
|
package/dist/realtime/topics.mjs
CHANGED
|
@@ -21,6 +21,6 @@ var t = /^[A-Za-z0-9:_.-]{1,128}$/, n = "[A-Za-z0-9_.-]{1,64}", r = (e) => t.tes
|
|
|
21
21
|
}, l = (e) => ({
|
|
22
22
|
maxMessageBytes: e.maxMessageBytes ?? 4096,
|
|
23
23
|
messagesPerSecond: e.messagesPerSecond ?? 30
|
|
24
|
-
}), u = "$presence", d = "$leave", f = "$join", p = "$revoked";
|
|
24
|
+
}), u = "$presence", d = "$leave", f = "$join", p = "$revoked", m = "plitzi-observer";
|
|
25
25
|
//#endregion
|
|
26
|
-
export { f as JOIN_TYPE, d as LEAVE_TYPE, u as PRESENCE_TYPE, p as REVOKED_TYPE, l as channelLimits, c as channelProblems, r as isValidTopic, a as matchChannel };
|
|
26
|
+
export { f as JOIN_TYPE, d as LEAVE_TYPE, m as OBSERVER_COOKIE_NAME, u as PRESENCE_TYPE, p as REVOKED_TYPE, l as channelLimits, c as channelProblems, r as isValidTopic, a as matchChannel };
|
package/dist/schema/index.mjs
CHANGED
|
@@ -2,6 +2,6 @@ import e from "./SchemaContext.mjs";
|
|
|
2
2
|
import { ANCHOR_PATTERN as t, anchorOf as n, isAnchor as r, uniqueAnchor as i } from "./anchor.mjs";
|
|
3
3
|
import { COMPONENT_PROPS_SOURCE as a, EMPTY_SCHEMA as o, VARIABLE_REGEX as s } from "./schemaConstants.mjs";
|
|
4
4
|
import { findLayoutCycle as c, resolveLayoutChain as l } from "./layoutChain.mjs";
|
|
5
|
-
import { collectServerElements as u, hasServerElements as d, notFoundProvider as f } from "./serverElements.mjs";
|
|
6
|
-
import { isSnippet as
|
|
7
|
-
export { t as ANCHOR_PATTERN, a as COMPONENT_PROPS_SOURCE, o as EMPTY_SCHEMA, e as SchemaContext, s as VARIABLE_REGEX, n as anchorOf, u as collectServerElements, c as findLayoutCycle, d as hasServerElements, r as isAnchor,
|
|
5
|
+
import { collectServerElements as u, hasServerElements as d, notFoundProvider as f, pageNotFound as p, pageSeoText as m, pageServerContext as h } from "./serverElements.mjs";
|
|
6
|
+
import { isSnippet as g } from "./snippet.mjs";
|
|
7
|
+
export { t as ANCHOR_PATTERN, a as COMPONENT_PROPS_SOURCE, o as EMPTY_SCHEMA, e as SchemaContext, s as VARIABLE_REGEX, n as anchorOf, u as collectServerElements, c as findLayoutCycle, d as hasServerElements, r as isAnchor, g as isSnippet, f as notFoundProvider, p as pageNotFound, m as pageSeoText, h as pageServerContext, l as resolveLayoutChain, i as uniqueAnchor };
|
|
@@ -20,9 +20,14 @@ import { Element, Schema } from '../types';
|
|
|
20
20
|
* Given the flags as they resolved, an element gated off by one is skipped with its whole subtree — it will not be
|
|
21
21
|
* rendered, so nothing in it wants data, and resolving it would put a feature that is off into the payload anyway.
|
|
22
22
|
*/
|
|
23
|
-
export declare const collectServerElements: (schema: Schema, pageId: string | undefined, ids?: string[], flags?: Record<string, boolean>) => Element[];
|
|
23
|
+
export declare const collectServerElements: (schema: Pick<Schema, "flat">, pageId: string | undefined, ids?: string[], flags?: Record<string, boolean>) => Element[];
|
|
24
24
|
/** Whether anything on this page consumes server data at all — the question both RSC gates actually ask. */
|
|
25
25
|
export declare const hasServerElements: (schema: Schema, pageId: string | undefined, flags?: Record<string, boolean>) => boolean;
|
|
26
|
+
/** Where the visitor is: what a template on the server reads beside the page's data, as `navigation`. */
|
|
27
|
+
export type ServerNavigation = {
|
|
28
|
+
routeParams: Record<string, unknown>;
|
|
29
|
+
queryParams: Record<string, unknown>;
|
|
30
|
+
};
|
|
26
31
|
/**
|
|
27
32
|
* The server provider of a page whose answer says the address shows nothing — its `notFound`, a template against
|
|
28
33
|
* that answer (`{{ source.found == false }}`) — by id; the page is then sent with status 404, rendered as written.
|
|
@@ -30,7 +35,23 @@ export declare const hasServerElements: (schema: Schema, pageId: string | undefi
|
|
|
30
35
|
* Only `true` counts: a template that does not evaluate comes back as its own text, and a typo must leave the page
|
|
31
36
|
* found rather than turn every visit into a 404.
|
|
32
37
|
*/
|
|
33
|
-
export declare const notFoundProvider: (elements: Element[], serverData: Record<string, unknown>, navigation:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
export declare const notFoundProvider: (elements: Element[], serverData: Record<string, unknown>, navigation: ServerNavigation) => string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* What a page's own templates read — its title, its description, its `notFound`: every server provider of the page and
|
|
41
|
+
* of the shells around it, by the name its descendants read it by (`apiContainer_capsule`), with its answer — and
|
|
42
|
+
* `navigation`. The server has both before it writes the head, and the browser has the same answer in `rsc.data`, so
|
|
43
|
+
* the two write one title.
|
|
44
|
+
*/
|
|
45
|
+
export declare const pageServerContext: (elements: Element[], serverData: Record<string, unknown>, navigation: ServerNavigation) => Record<string, unknown>;
|
|
46
|
+
/**
|
|
47
|
+
* A page's title or description as the head carries it: its words, or its template evaluated against
|
|
48
|
+
* `pageServerContext`. Blank, or a template that did not evaluate — it comes back as its own text — is nothing, and the
|
|
49
|
+
* deployment's own title stays: braces never reach a tab or a link preview.
|
|
50
|
+
*/
|
|
51
|
+
export declare const pageSeoText: (value: unknown, context: Record<string, unknown>) => string | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Whether a page's own `notFound` — a template over `pageServerContext` — says the address shows nothing: a record
|
|
54
|
+
* read by a provider the page shares with others, in its layout, which cannot say it for any one page itself. Only
|
|
55
|
+
* `true` counts, as for a provider's.
|
|
56
|
+
*/
|
|
57
|
+
export declare const pageNotFound: (template: unknown, context: Record<string, unknown>) => boolean;
|
|
@@ -1,27 +1,35 @@
|
|
|
1
1
|
import { processTwigValue as e } from "../helpers/twigWrapper/processTwig/processTwig.mjs";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import t from "../dataSource/helpers/getSourceName.mjs";
|
|
3
|
+
import { passesFlagGate as n } from "../flags/resolveFlags.mjs";
|
|
4
|
+
import { resolveLayoutChain as r } from "./layoutChain.mjs";
|
|
4
5
|
//#region src/schema/serverElements.ts
|
|
5
|
-
var
|
|
6
|
-
if (
|
|
7
|
-
let o = i ? new Set(i) : void 0, s = [], c = /* @__PURE__ */ new Set(), l = e.flat[
|
|
6
|
+
var i = (e, t, i, a) => {
|
|
7
|
+
if (t === void 0) return [];
|
|
8
|
+
let o = i ? new Set(i) : void 0, s = [], c = /* @__PURE__ */ new Set(), l = e.flat[t], u = (e) => typeof e == "string" ? e : "", d = [t, ...l ? r((t) => e.flat[t], u(l.attributes.layout), u(l.attributes.layoutContainer)).map((e) => e.layout) : []];
|
|
8
9
|
for (; d.length > 0;) {
|
|
9
|
-
let
|
|
10
|
-
if (
|
|
11
|
-
c.add(
|
|
12
|
-
let r = e.flat[
|
|
13
|
-
if (!r || a && !
|
|
10
|
+
let t = d.pop();
|
|
11
|
+
if (t === void 0 || c.has(t)) continue;
|
|
12
|
+
c.add(t);
|
|
13
|
+
let r = e.flat[t];
|
|
14
|
+
if (!r || a && !n(r.definition.flag, a)) continue;
|
|
14
15
|
r.definition.runtime === "server" && (!o || o.has(r.id)) && s.push(r);
|
|
15
16
|
let { items: i } = r.definition;
|
|
16
17
|
i && d.push(...i);
|
|
17
18
|
}
|
|
18
19
|
return s;
|
|
19
|
-
},
|
|
20
|
+
}, a = (e, t, n) => i(e, t, void 0, n).length > 0, o = (t, n, r) => t.find((t) => {
|
|
20
21
|
let i = t.attributes.notFound;
|
|
21
22
|
return typeof i == "string" && i !== "" && Object.hasOwn(n, t.id) && e(i, {
|
|
22
23
|
source: n[t.id],
|
|
23
24
|
navigation: r
|
|
24
25
|
}) === !0;
|
|
25
|
-
})?.id
|
|
26
|
+
})?.id, s = (e, n, r) => ({
|
|
27
|
+
...Object.fromEntries(e.filter((e) => Object.hasOwn(n, e.id)).map((e) => [t(e.definition.type, e.id), n[e.id]])),
|
|
28
|
+
navigation: r
|
|
29
|
+
}), c = /\{[{%]/, l = (t, n) => {
|
|
30
|
+
if (typeof t != "string") return;
|
|
31
|
+
let r = c.test(t) ? e(t, n) : t, i = typeof r == "string" || typeof r == "number" ? String(r).trim() : "";
|
|
32
|
+
return i === "" || c.test(i) ? void 0 : i;
|
|
33
|
+
}, u = (t, n) => typeof t == "string" && t !== "" && e(t, n) === !0;
|
|
26
34
|
//#endregion
|
|
27
|
-
export {
|
|
35
|
+
export { i as collectServerElements, a as hasServerElements, o as notFoundProvider, u as pageNotFound, l as pageSeoText, s as pageServerContext };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
export type ElementSize = {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* The size an element is drawn at — a plugin's own box, which a sidebar, a panel or a split screen makes narrower than
|
|
8
|
+
* the window — kept up to date as it changes. What `useDisplayMode` cannot say: a tablet held upright is `mobile` by
|
|
9
|
+
* the window's breakpoints, and a week of seven columns still fits the 744 px the plugin has.
|
|
10
|
+
*
|
|
11
|
+
* `undefined` until it is measured: on the server, and in the browser's first render, so the page the server sent and
|
|
12
|
+
* the one that hydrates it are the same. Decide from a fallback until then — the breakpoint's guess:
|
|
13
|
+
* `const days = (size?.width ?? (useDisplayMode() === 'mobile' ? 390 : 1024)) >= 640 ? 7 : 3`.
|
|
14
|
+
*/
|
|
15
|
+
declare const useElementSize: (ref: RefObject<HTMLElement | null>) => ElementSize | undefined;
|
|
16
|
+
export default useElementSize;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useEffect as e, useState as t } from "react";
|
|
2
|
+
//#region src/style/useElementSize.ts
|
|
3
|
+
var n = (n) => {
|
|
4
|
+
let [r, i] = t(void 0);
|
|
5
|
+
return e(() => {
|
|
6
|
+
let e = n.current;
|
|
7
|
+
if (!e || typeof ResizeObserver > "u") return;
|
|
8
|
+
let t = (e, t) => i((n) => n?.width === e && n.height === t ? n : {
|
|
9
|
+
width: e,
|
|
10
|
+
height: t
|
|
11
|
+
}), r = e.getBoundingClientRect();
|
|
12
|
+
t(r.width, r.height);
|
|
13
|
+
let a = new ResizeObserver((e) => {
|
|
14
|
+
e.slice(-1).forEach((e) => t(e.contentRect.width, e.contentRect.height));
|
|
15
|
+
});
|
|
16
|
+
return a.observe(e), () => a.disconnect();
|
|
17
|
+
}, [n]), r;
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { n as default };
|
|
@@ -1,60 +1,69 @@
|
|
|
1
1
|
import { useCommonStoreSync as e } from "../store/index.mjs";
|
|
2
2
|
import { THEME_COOKIE_NAME as t, applyThemeClass as n, readThemeCookie as r, writeThemeCookie as i } from "./themeCookie.mjs";
|
|
3
3
|
import a, { createThemeStore as o, resolveScheme as s, setMachineScheme as c, setThemeMode as l } from "./themeStore.mjs";
|
|
4
|
-
import u from "./ThemeScope.mjs";
|
|
5
|
-
import { use as
|
|
6
|
-
import { StoreContext as
|
|
7
|
-
import {
|
|
4
|
+
import u, { ThemeStartContext as d, useThemeState as f } from "./ThemeScope.mjs";
|
|
5
|
+
import { use as p, useEffect as m, useId as h, useRef as g, useState as _ } from "react";
|
|
6
|
+
import { StoreContext as v, useIsomorphicLayoutEffect as y } from "@plitzi/nexus/react";
|
|
7
|
+
import { jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
8
8
|
//#region src/theme/ThemeProvider.tsx
|
|
9
|
-
var S = "(prefers-color-scheme: dark)", C = () => window.matchMedia(S).matches ? "dark" : "light", w = ({
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
var S = "(prefers-color-scheme: dark)", C = () => window.matchMedia(S).matches ? "dark" : "light", w = ({ store: t }) => {
|
|
10
|
+
let n = f(t);
|
|
11
|
+
return e([
|
|
12
|
+
"theme.mode",
|
|
13
|
+
"theme.resolved",
|
|
14
|
+
"theme.areas"
|
|
15
|
+
], [
|
|
16
|
+
n.mode,
|
|
17
|
+
s(n.mode, n.scheme),
|
|
18
|
+
n.areas
|
|
19
|
+
]), null;
|
|
20
|
+
}, T = ({ defaultTheme: e = "system", theme: s, scope: f = "document", cookieName: T = t, children: E }) => {
|
|
21
|
+
let D = f === "container", O = h(), [k] = _(() => D ? o(`theme${O}`) : void 0), A = k ?? a, j = g({
|
|
19
22
|
mode: e,
|
|
20
23
|
remembered: !1
|
|
21
24
|
});
|
|
22
|
-
|
|
23
|
-
let t =
|
|
24
|
-
|
|
25
|
+
y(() => {
|
|
26
|
+
let t = D ? void 0 : r(T), n = s ?? t ?? e;
|
|
27
|
+
j.current = {
|
|
25
28
|
mode: n,
|
|
26
29
|
remembered: t !== void 0
|
|
27
|
-
},
|
|
28
|
-
c(C(),
|
|
30
|
+
}, A.batch(() => {
|
|
31
|
+
c(C(), A), l(n, A);
|
|
29
32
|
});
|
|
30
33
|
}, [
|
|
31
34
|
e,
|
|
32
35
|
s,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
T,
|
|
37
|
+
D,
|
|
38
|
+
A
|
|
36
39
|
]);
|
|
37
|
-
let
|
|
38
|
-
|
|
39
|
-
let e = window.matchMedia(S), t = () => c(e.matches ? "dark" : "light",
|
|
40
|
+
let M = s ?? e, N = p(v) !== void 0;
|
|
41
|
+
m(() => {
|
|
42
|
+
let e = window.matchMedia(S), t = () => c(e.matches ? "dark" : "light", A);
|
|
40
43
|
return e.addEventListener("change", t), t(), () => e.removeEventListener("change", t);
|
|
41
|
-
}, [
|
|
42
|
-
if (
|
|
44
|
+
}, [A]), m(() => {
|
|
45
|
+
if (D) return;
|
|
43
46
|
let e = () => {
|
|
44
|
-
let { mode: e } =
|
|
45
|
-
(
|
|
47
|
+
let { mode: e } = A.getState();
|
|
48
|
+
(j.current.remembered || e !== j.current.mode) && (i(e, T), j.current.remembered = !0), n(e, document.documentElement);
|
|
46
49
|
};
|
|
47
|
-
return e(),
|
|
50
|
+
return e(), A.subscribe(e);
|
|
48
51
|
}, [
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
T,
|
|
53
|
+
D,
|
|
54
|
+
A
|
|
52
55
|
]);
|
|
53
|
-
let
|
|
54
|
-
return
|
|
55
|
-
value:
|
|
56
|
-
children:
|
|
57
|
-
|
|
56
|
+
let P = N ? /* @__PURE__ */ b(w, { store: A }) : null;
|
|
57
|
+
return D ? /* @__PURE__ */ b(u, {
|
|
58
|
+
value: k,
|
|
59
|
+
children: /* @__PURE__ */ x(d, {
|
|
60
|
+
value: M,
|
|
61
|
+
children: [P, E]
|
|
62
|
+
})
|
|
63
|
+
}) : /* @__PURE__ */ x(d, {
|
|
64
|
+
value: M,
|
|
65
|
+
children: [P, E]
|
|
66
|
+
});
|
|
58
67
|
};
|
|
59
68
|
//#endregion
|
|
60
69
|
export { T as default };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ThemeStoreInstance } from './themeStore';
|
|
2
|
+
import { Theme, ThemeState } from '../types';
|
|
2
3
|
/**
|
|
3
4
|
* Which theme store the tree under here reads.
|
|
4
5
|
*
|
|
@@ -11,6 +12,25 @@ import { ThemeStoreInstance } from './themeStore';
|
|
|
11
12
|
* Deliberately NOT the way ordinary consumers reach the theme: a panel in a shadow root and an editor in a portal
|
|
12
13
|
* are under no provider at all, and they still have to get an answer. That is what the fall-through is for.
|
|
13
14
|
*/
|
|
14
|
-
declare const ThemeScopeContext: import('react').Context<import('@plitzi/nexus').StoreApi<
|
|
15
|
+
declare const ThemeScopeContext: import('react').Context<import('@plitzi/nexus').StoreApi<ThemeState> | undefined>;
|
|
15
16
|
export declare const useThemeStore: () => ThemeStoreInstance;
|
|
16
17
|
export default ThemeScopeContext;
|
|
18
|
+
/**
|
|
19
|
+
* The mode the surface under a `ThemeProvider` starts in: the theme its host supplied — the cookie a server read — or
|
|
20
|
+
* else its default.
|
|
21
|
+
*
|
|
22
|
+
* For the render that runs before any effect can: the server's, and the hydration that has to agree with it. The
|
|
23
|
+
* provider sets the store from a layout effect, which never runs on a server — so the page was rendered from the
|
|
24
|
+
* store's own starting state, `system` resolving to `light`, whatever the cookie said. The class on `<html>` was right
|
|
25
|
+
* and `{{ theme.resolved }}` was not: a picture whose address names the scheme was the light one, swapped for the dark
|
|
26
|
+
* one as the page hydrated.
|
|
27
|
+
*/
|
|
28
|
+
export declare const ThemeStartContext: import('react').Context<Theme | undefined>;
|
|
29
|
+
/**
|
|
30
|
+
* The theme store's state, as the server rendered it until the surface is live.
|
|
31
|
+
*
|
|
32
|
+
* The starting state is the server snapshot, so the server renders with it and the hydration reads the same — it is
|
|
33
|
+
* never written into the store there, which on a server is one module-level singleton every request shares. Once
|
|
34
|
+
* hydrated, the store answers, which the provider has set by then.
|
|
35
|
+
*/
|
|
36
|
+
export declare const useThemeState: (store: ThemeStoreInstance) => ThemeState;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { sharedContext as e } from "../helpers/sharedContext.mjs";
|
|
2
|
-
import t from "./themeStore.mjs";
|
|
3
|
-
import { use as
|
|
2
|
+
import t, { startingThemeState as n } from "./themeStore.mjs";
|
|
3
|
+
import { use as r, useMemo as i, useSyncExternalStore as a } from "react";
|
|
4
4
|
//#region src/theme/ThemeScope.ts
|
|
5
|
-
var
|
|
5
|
+
var o = e("ThemeScopeContext", void 0), s = () => r(o) ?? t, c = e("ThemeStartContext", void 0), l = (e) => {
|
|
6
|
+
let t = r(c), o = i(() => t === void 0 ? void 0 : n(t), [t]);
|
|
7
|
+
return a(e.subscribe, e.getState, () => o ?? e.getState());
|
|
8
|
+
};
|
|
6
9
|
//#endregion
|
|
7
|
-
export {
|
|
10
|
+
export { c as ThemeStartContext, o as default, l as useThemeState, s as useThemeStore };
|
package/dist/theme/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { THEME_CLASSES as e, THEME_COOKIE_NAME as t, applyThemeClass as n, isTheme as r, readThemeCookie as i, themeFromCookies as a, writeThemeCookie as o } from "./themeCookie.mjs";
|
|
2
|
-
import s, { createThemeState as c, createThemeStore as l, resolveScheme as u, setAreaTheme as d, setMachineScheme as f, setThemeMode as p,
|
|
3
|
-
import { useThemeStore as
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
export {
|
|
2
|
+
import s, { createThemeState as c, createThemeStore as l, resolveScheme as u, setAreaTheme as d, setMachineScheme as f, setThemeMode as p, startingThemeState as m, themeFor as h } from "./themeStore.mjs";
|
|
3
|
+
import { ThemeStartContext as g, useThemeState as _, useThemeStore as v } from "./ThemeScope.mjs";
|
|
4
|
+
import y from "./ThemeProvider.mjs";
|
|
5
|
+
import b, { SPACE_THEME_AREA as x } from "./useTheme.mjs";
|
|
6
|
+
export { x as SPACE_THEME_AREA, e as THEME_CLASSES, t as THEME_COOKIE_NAME, y as ThemeProvider, g as ThemeStartContext, n as applyThemeClass, c as createThemeState, l as createThemeStore, r as isTheme, i as readThemeCookie, u as resolveScheme, d as setAreaTheme, f as setMachineScheme, p as setThemeMode, m as startingThemeState, h as themeFor, a as themeFromCookies, s as themeStore, b as useTheme, _ as useThemeState, v as useThemeStore, o as writeThemeCookie };
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ColorScheme, Theme, ThemeState } from '../types';
|
|
2
2
|
export declare const createThemeState: () => ThemeState;
|
|
3
|
+
/**
|
|
4
|
+
* The state a surface starts in, before anything could ask the machine: the mode it opens with, and `light` for what a
|
|
5
|
+
* `system` mode resolves to until the browser answers — the one guess a server has to make, and the one the
|
|
6
|
+
* stylesheet's media queries correct without a class.
|
|
7
|
+
*/
|
|
8
|
+
export declare const startingThemeState: (mode: Theme) => ThemeState;
|
|
3
9
|
/**
|
|
4
10
|
* The theme, as a store rather than a context.
|
|
5
11
|
*
|
|
@@ -4,14 +4,17 @@ var t = () => ({
|
|
|
4
4
|
mode: "system",
|
|
5
5
|
scheme: "light",
|
|
6
6
|
areas: {}
|
|
7
|
-
}), n = (
|
|
7
|
+
}), n = (e) => ({
|
|
8
|
+
...t(),
|
|
9
|
+
mode: e
|
|
10
|
+
}), r = (n = "theme") => e(t(), { id: n }), i = r(), a = (e, t) => e === "system" ? t : e, o = (e, t) => (t ? e.areas[t] : void 0) ?? e.mode, s = (e, t = i) => {
|
|
8
11
|
t.batch(() => {
|
|
9
12
|
t.setState("mode", e), t.setState("areas", {});
|
|
10
13
|
});
|
|
11
|
-
},
|
|
14
|
+
}, c = (e, t, n = i) => {
|
|
12
15
|
n.setState(`areas.${e}`, t);
|
|
13
|
-
},
|
|
16
|
+
}, l = (e, t = i) => {
|
|
14
17
|
t.setState("scheme", e);
|
|
15
18
|
};
|
|
16
19
|
//#endregion
|
|
17
|
-
export { t as createThemeState,
|
|
20
|
+
export { t as createThemeState, r as createThemeStore, i as default, a as resolveScheme, c as setAreaTheme, l as setMachineScheme, s as setThemeMode, n as startingThemeState, o as themeFor };
|
package/dist/theme/useTheme.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { resolveScheme as e, setAreaTheme as t, setThemeMode as n, themeFor as r } from "./themeStore.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { useCallback as
|
|
2
|
+
import { useThemeState as i, useThemeStore as a } from "./ThemeScope.mjs";
|
|
3
|
+
import { useCallback as o, useMemo as s } from "react";
|
|
4
4
|
//#region src/theme/useTheme.ts
|
|
5
5
|
var c = "canvas", l = (c) => {
|
|
6
|
-
let l =
|
|
7
|
-
return
|
|
6
|
+
let l = a(), u = i(l), d = r(u, c), f = e(d, u.scheme), p = o((e) => c ? t(c, e, l) : n(e, l), [c, l]), m = o(() => p(f === "dark" ? "light" : "dark"), [f, p]);
|
|
7
|
+
return s(() => ({
|
|
8
8
|
theme: d,
|
|
9
9
|
resolvedTheme: f,
|
|
10
10
|
setTheme: p,
|
|
@@ -70,10 +70,11 @@ export type ActionWebhookVerification = {
|
|
|
70
70
|
* The ways into an action, as the `action` of a trigger STEP rather than a list beside the flow.
|
|
71
71
|
*
|
|
72
72
|
* `call` — a client flow through the action endpoint. `webhook` — an inbound request, public by construction.
|
|
73
|
-
* `schedule` — a cron tick. `
|
|
74
|
-
*
|
|
73
|
+
* `schedule` — a cron tick. `later` — a run another one set to start N seconds from then (`ctx.later`, `flow.later`):
|
|
74
|
+
* a turn that runs out, a bot's move, a hold that lapses. `render` — a `runtime: 'server'` element naming this action.
|
|
75
|
+
* `custom` — a trigger the deployment mounted itself.
|
|
75
76
|
*/
|
|
76
|
-
export type ActionTriggerType = 'call' | 'webhook' | 'schedule' | 'render' | 'custom';
|
|
77
|
+
export type ActionTriggerType = 'call' | 'webhook' | 'schedule' | 'later' | 'render' | 'custom';
|
|
77
78
|
/**
|
|
78
79
|
* What a trigger step carries, in its `params`.
|
|
79
80
|
*
|
|
@@ -551,6 +552,11 @@ export type ActionJobInput = {
|
|
|
551
552
|
maxAttempts: number;
|
|
552
553
|
/** Fires that went by unclaimed before this one. Shown to an operator; never acted on. */
|
|
553
554
|
missed?: number;
|
|
555
|
+
/**
|
|
556
|
+
* What a run set to run later (`trigger: 'later'`) was named by: setting it again under the same name replaces the
|
|
557
|
+
* one still waiting, and cancelling it by name drops it.
|
|
558
|
+
*/
|
|
559
|
+
key?: string;
|
|
554
560
|
};
|
|
555
561
|
/** One unit of work the queue is holding, as an operator sees it. */
|
|
556
562
|
export type ActionJob = ActionJobInput & {
|
|
@@ -692,4 +698,14 @@ export type ActionJobQueue = {
|
|
|
692
698
|
requeue: (spaceIds: number[], jobId: string) => Promise<boolean>;
|
|
693
699
|
/** An operator stopping a job: dropped if it is waiting, aborted at its next step if it is running. */
|
|
694
700
|
cancel: (spaceIds: number[], jobId: string) => Promise<boolean>;
|
|
701
|
+
/**
|
|
702
|
+
* Drops the space's jobs waiting under `key` (`cancelled`), and answers how many. With `olderThan`, only the ones
|
|
703
|
+
* enqueued before that job — created earlier, or at the same instant with a smaller id — so of two set at once the
|
|
704
|
+
* newer is the one left, on every replica. A running one is left: it is usually the run that set the next.
|
|
705
|
+
*/
|
|
706
|
+
cancelPending: (params: {
|
|
707
|
+
spaceId: number;
|
|
708
|
+
key: string;
|
|
709
|
+
olderThan?: string;
|
|
710
|
+
}) => Promise<number>;
|
|
695
711
|
};
|
|
@@ -50,9 +50,22 @@ export type RealtimeMessage = RealtimeSender & {
|
|
|
50
50
|
data: unknown;
|
|
51
51
|
/** Server time, in milliseconds. */
|
|
52
52
|
at: number;
|
|
53
|
+
/**
|
|
54
|
+
* The sender asked to hear it too ({@link RealtimePublishOptions}): it reaches the page that sent it as well, which
|
|
55
|
+
* knows it for its own by `from` — its channel's `me`. Without it, a page never hears what it sent.
|
|
56
|
+
*/
|
|
57
|
+
echo?: true;
|
|
58
|
+
};
|
|
59
|
+
/** What a page asks of a publish beyond the message itself. */
|
|
60
|
+
export type RealtimePublishOptions = {
|
|
61
|
+
/**
|
|
62
|
+
* Hear it too, once the server took it — a reaction, a chat line: what the sender shows the moment it sends. Off by
|
|
63
|
+
* default, so what moves at the speed of a cursor is not drawn twice.
|
|
64
|
+
*/
|
|
65
|
+
echo?: boolean;
|
|
53
66
|
};
|
|
54
67
|
/** What a page sends to publish: the secret its connection was given, and the message. */
|
|
55
|
-
export type RealtimePublishRequest = {
|
|
68
|
+
export type RealtimePublishRequest = RealtimePublishOptions & {
|
|
56
69
|
token: string;
|
|
57
70
|
topic: string;
|
|
58
71
|
type: string;
|
|
@@ -1185,7 +1185,12 @@ export type SSRContext = {
|
|
|
1185
1185
|
rscParams?: Record<string, string>;
|
|
1186
1186
|
};
|
|
1187
1187
|
export type SSRServer = {
|
|
1188
|
-
|
|
1188
|
+
/**
|
|
1189
|
+
* Binds the port. Resolves once it takes connections — in a fleet, once the first worker does — so what says "ready"
|
|
1190
|
+
* (a log line, a file a tool reads, a test's first request) says it after, never before. A port it could not take
|
|
1191
|
+
* ends the process, or goes to `onListenError`: the promise is then never resolved.
|
|
1192
|
+
*/
|
|
1193
|
+
listen: (port: number, host?: string) => Promise<void>;
|
|
1189
1194
|
close: () => Promise<void>;
|
|
1190
1195
|
readonly cache: CacheManager | null;
|
|
1191
1196
|
readonly plugins: PluginRegistry;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plitzi/sdk-shared",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.11",
|
|
4
4
|
"license": "AGPL-3.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -1431,6 +1431,10 @@
|
|
|
1431
1431
|
"types": "./dist/style/useDisplayMode.d.ts",
|
|
1432
1432
|
"import": "./dist/style/useDisplayMode.mjs"
|
|
1433
1433
|
},
|
|
1434
|
+
"./style/useElementSize": {
|
|
1435
|
+
"types": "./dist/style/useElementSize.d.ts",
|
|
1436
|
+
"import": "./dist/style/useElementSize.mjs"
|
|
1437
|
+
},
|
|
1434
1438
|
"./theme": {
|
|
1435
1439
|
"types": "./dist/theme/index.d.ts",
|
|
1436
1440
|
"import": "./dist/theme/index.mjs"
|
|
@@ -1576,7 +1580,7 @@
|
|
|
1576
1580
|
},
|
|
1577
1581
|
"dependencies": {
|
|
1578
1582
|
"@plitzi/nexus": "^1.4.0",
|
|
1579
|
-
"@plitzi/plitzi-ui": "^1.6.
|
|
1583
|
+
"@plitzi/plitzi-ui": "^1.6.33",
|
|
1580
1584
|
"date-fns": "^4.4.0",
|
|
1581
1585
|
"immer": "^11.1.21",
|
|
1582
1586
|
"zod": "^4.6.5"
|