phoenix_duskmoon 10.0.11 → 10.1.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/CHANGELOG.md CHANGED
@@ -1,3 +1,42 @@
1
+ # [10.1.0](https://github.com/duskmoon-dev/phoenix-duskmoon-ui/compare/v10.0.12...v10.1.0) (2026-11-07)
2
+
3
+ ### Added
4
+
5
+ - Add opt-in structured composer protocol v1 to React Chat, including semantic
6
+ documents, context-scoped projections, explicit admission receipts, uncertain
7
+ submission recovery, and queue removal through LiveView events.
8
+ - Demonstrate composer permissions, commands, steering, queued follow-ups, and
9
+ reconnect recovery in Storybook while preserving the legacy text submission API.
10
+ - Expose the optional rich editor through lazy imports, with packaged consumer
11
+ checks that keep Lexical out of ordinary chat and hooks bundles.
12
+
13
+ ### Changed
14
+
15
+ - Adopt Core/CSS Art 1.21.0, Elements/Art Elements 1.10.2, and React Components
16
+ 0.6.0 with optional Lexical 0.53.0 peers.
17
+ - Update the published Bundler cohort to 10.1.2, the HTTP clients to 1.0.0-rc.5,
18
+ Gaoxy HTTP and its WebSock adapter to 0.15.1, and Tailwind to 4.3.5.
19
+ - Build Storybook images on Ubuntu 26.04 to meet the published native
20
+ toolchain's glibc 2.43 requirement.
21
+
22
+ ### Fixed
23
+
24
+ - Restore production HTTP admission in private cgroup namespaces by adopting
25
+ Gaoxy's mount visibility fix for overmounted memory controllers.
26
+ - Preserve React-owned values for disabled native form controls instead of
27
+ removing them when the browser omits disabled fields, resolving
28
+ [#210](https://github.com/duskmoon-dev/phoenix-duskmoon-ui/issues/210).
29
+
30
+ # [10.0.12](https://github.com/duskmoon-dev/phoenix-duskmoon-ui/compare/v10.0.11...v10.0.12) (2026-11-01)
31
+
32
+ ### Fixed
33
+
34
+ - Exclude build-tool applications (`duskmoon_npm`, `duskmoon_hex_solver`, etc.) from
35
+ Storybook production release assembly, ensuring a clean runtime-only release.
36
+ - Add Bun setup to test workflow for browser component tests.
37
+ - Bump `@duskmoon-dev/components` to 0.5.5 for Popover API support, dropdown select
38
+ layout, and timeline marker styling.
39
+
1
40
  # [10.0.11](https://github.com/duskmoon-dev/phoenix-duskmoon-ui/compare/v10.0.10...v10.0.11) (2026-10-22)
2
41
 
3
42
  ### Fixed
package/README.md CHANGED
@@ -32,13 +32,13 @@ Add to `mix.exs`:
32
32
  Install frontend packages:
33
33
 
34
34
  ```bash
35
- bun add @duskmoon-dev/core @duskmoon-dev/elements
35
+ mix npm.install @duskmoon-dev/core @duskmoon-dev/elements
36
36
  ```
37
37
 
38
38
  Optionally, add CSS Art and Art Custom Elements support:
39
39
 
40
40
  ```bash
41
- bun add @duskmoon-dev/css-art @duskmoon-dev/art-elements
41
+ mix npm.install @duskmoon-dev/css-art @duskmoon-dev/art-elements
42
42
  ```
43
43
 
44
44
  ### View Helpers
@@ -189,12 +189,19 @@ application's upload mechanism; they cannot be sent as LiveView JSON payloads.
189
189
  ## Repository development
190
190
 
191
191
  This checkout contains the UI and Storybook. It consumes the published toolchain
192
- cohort pinned in `BUNDLER_VERSION` and `mix.lock`; ordinary UI builds use verified
193
- precompiled Duskmoon native artifacts. The toolchain source and its own releases
194
- live in [duskmoon-bundler](https://github.com/duskmoon-dev/duskmoon-bundler).
192
+ cohort declared with `~> 10.0` requirements and resolved in `mix.lock`; ordinary UI
193
+ builds use verified precompiled Duskmoon native artifacts. The toolchain source
194
+ and its own releases live in [duskmoon-bundler](https://github.com/duskmoon-dev/duskmoon-bundler).
195
195
  See the [migration and development guide](docs/bundler-extraction.md) for setup,
196
196
  candidate integration and independent release order.
197
197
 
198
+ Storybook also consumes `duskmoon_hologram ~> 10.0` and provides a Hologram section
199
+ before Storybook in its top navigation. Run `mix duskmoon.dev` (or `mix holo`) and
200
+ open `/hologram` for the component playground, task list and profile preview.
201
+ The checkout requires OTP 28+; `phoenix_duskmoon` itself keeps its existing Elixir
202
+ and Phoenix compatibility and does not depend on Hologram. See the
203
+ [Hologram guide](docs/hologram-example.md) for runtime boundaries and verification.
204
+
198
205
  ## Live Storybook
199
206
 
200
207
  [Live Storybook](https://duskmoon-storybook.gsmlg.dev)
@@ -3,6 +3,7 @@ import { Markdown } from "@duskmoon-dev/components/markdown";
3
3
  import { Input } from "@duskmoon-dev/components/input";
4
4
  import { Button } from "@duskmoon-dev/components/button";
5
5
  import { Chat } from "@duskmoon-dev/components/chat";
6
+ import { requestId } from "./protocol.js";
6
7
  const h = React.createElement;
7
8
  const defaultOptions = {};
8
9
 
@@ -131,21 +132,6 @@ const Message = memo(function Message(props) {
131
132
  );
132
133
  });
133
134
 
134
- function requestId() {
135
- if (typeof crypto.randomUUID === "function") return crypto.randomUUID();
136
- const bytes = crypto.getRandomValues(new Uint8Array(16));
137
- bytes[6] = (bytes[6] & 0x0f) | 0x40;
138
- bytes[8] = (bytes[8] & 0x3f) | 0x80;
139
- const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
140
- return [
141
- hex.slice(0, 4).join(""),
142
- hex.slice(4, 6).join(""),
143
- hex.slice(6, 8).join(""),
144
- hex.slice(8, 10).join(""),
145
- hex.slice(10).join(""),
146
- ].join("-");
147
- }
148
-
149
135
  // A composer owns its draft/attachments. This helper only owns admission and UI requests.
150
136
  export function useChatSubmission({ bridge, canSubmit }) {
151
137
  const [busy, setBusy] = useState(false);
@@ -165,6 +151,9 @@ export function useChatSubmission({ bridge, canSubmit }) {
165
151
  setBusy(true);
166
152
  setNotice("");
167
153
  try {
154
+ const structured =
155
+ payload.protocolVersion !== undefined || payload.document !== undefined;
156
+ if (structured) return await bridge.submit(payload);
168
157
  return await bridge.send("send", {
169
158
  request_id: requestId(),
170
159
  ...payload,
@@ -237,6 +226,7 @@ export function ReactChat({
237
226
  connected,
238
227
  label,
239
228
  options = defaultOptions,
229
+ adapter,
240
230
  }) {
241
231
  const transcriptId = useId();
242
232
  const scroll = useRef(null);
@@ -258,6 +248,11 @@ export function ReactChat({
258
248
  state,
259
249
  bridge,
260
250
  connected,
251
+ adapter,
252
+ scope: state.scope,
253
+ instanceGeneration: state.instanceGeneration,
254
+ composer: state.composer,
255
+ providers: adapter?.providers,
261
256
  synchronizing: state.needsSync,
262
257
  metadata: state.metadata,
263
258
  runtime: state.runtime,
@@ -344,9 +339,13 @@ export function ReactChat({
344
339
  : "Disconnected. Draft preserved.",
345
340
  ),
346
341
  options.renderStatus && h(options.renderStatus, context),
342
+ state.error && h("p", { role: "alert" }, state.error),
347
343
  h(options.Composer || DefaultComposer, {
348
344
  ...context,
349
- key: state.conversationId,
345
+ key:
346
+ state.protocolVersion === 1
347
+ ? state.instanceGeneration
348
+ : state.conversationId,
350
349
  }),
351
350
  );
352
351
  }