@mieweb/ui 0.11.0-dev.36 → 0.11.0-dev.38
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/agent/README.md +1 -1
- package/agent/agents/mieweb-ui-design.agent.md +12 -7
- package/agent/agents/mieweb-ui-migration.agent.md +144 -0
- package/agent/skills/mieweb-ui-catalog/SKILL.md +8 -6
- package/agent/skills/mieweb-ui-catalog/selection-guidance.md +9 -5
- package/dist/{chunk-TUYWCUKH.js → chunk-4LKAZW2W.js} +7 -3
- package/dist/chunk-4LKAZW2W.js.map +1 -0
- package/dist/{chunk-MNXIN4MS.js → chunk-5WA6IYZD.js} +60 -2
- package/dist/chunk-5WA6IYZD.js.map +1 -0
- package/dist/{chunk-DT3X3RBM.js → chunk-7U7SONM5.js} +3 -3
- package/dist/{chunk-DT3X3RBM.js.map → chunk-7U7SONM5.js.map} +1 -1
- package/dist/{chunk-OGFSFUIX.cjs → chunk-AHYDJN4H.cjs} +501 -120
- package/dist/chunk-AHYDJN4H.cjs.map +1 -0
- package/dist/{chunk-C4GEPUE7.js → chunk-CKECOCYJ.js} +2 -2
- package/dist/{chunk-C4GEPUE7.js.map → chunk-CKECOCYJ.js.map} +1 -1
- package/dist/{chunk-V5VPECJI.js → chunk-CRR7AE5D.js} +11 -7
- package/dist/chunk-CRR7AE5D.js.map +1 -0
- package/dist/chunk-D3FNZMOB.cjs +4 -0
- package/dist/{chunk-GLXTVCHN.cjs.map → chunk-D3FNZMOB.cjs.map} +1 -1
- package/dist/{chunk-ZK2R6UGF.cjs → chunk-DCV34MEF.cjs} +4 -4
- package/dist/{chunk-ZK2R6UGF.cjs.map → chunk-DCV34MEF.cjs.map} +1 -1
- package/dist/chunk-G4VQEQGW.js +3 -0
- package/dist/{chunk-RISZWWEQ.js.map → chunk-G4VQEQGW.js.map} +1 -1
- package/dist/{chunk-S3LTUSO5.cjs → chunk-GG3IK5TL.cjs} +7 -7
- package/dist/{chunk-S3LTUSO5.cjs.map → chunk-GG3IK5TL.cjs.map} +1 -1
- package/dist/{chunk-QHCAWDMG.cjs → chunk-HDZQLTBP.cjs} +7 -3
- package/dist/chunk-HDZQLTBP.cjs.map +1 -0
- package/dist/chunk-JCIQIR5V.js +546 -0
- package/dist/chunk-JCIQIR5V.js.map +1 -0
- package/dist/{chunk-AIO2GCTL.js → chunk-JUY2JLFL.js} +501 -120
- package/dist/chunk-JUY2JLFL.js.map +1 -0
- package/dist/{chunk-2S76TRBJ.cjs → chunk-JUYBJLPI.cjs} +4 -4
- package/dist/{chunk-2S76TRBJ.cjs.map → chunk-JUYBJLPI.cjs.map} +1 -1
- package/dist/{chunk-UDUYZDTA.js → chunk-JWMMWNTT.js} +3 -3
- package/dist/{chunk-UDUYZDTA.js.map → chunk-JWMMWNTT.js.map} +1 -1
- package/dist/{chunk-RM4CBS7Y.js → chunk-LQ22CY7X.js} +4 -4
- package/dist/{chunk-RM4CBS7Y.js.map → chunk-LQ22CY7X.js.map} +1 -1
- package/dist/{chunk-AKMTPCLC.cjs → chunk-LTCHD3K5.cjs} +2 -2
- package/dist/{chunk-AKMTPCLC.cjs.map → chunk-LTCHD3K5.cjs.map} +1 -1
- package/dist/{chunk-GDKOYVX3.cjs → chunk-NZUQL42A.cjs} +11 -7
- package/dist/chunk-NZUQL42A.cjs.map +1 -0
- package/dist/chunk-QAEAC7HO.cjs +4 -0
- package/dist/chunk-QAEAC7HO.cjs.map +1 -0
- package/dist/chunk-SCGXD334.js +3 -0
- package/dist/chunk-SCGXD334.js.map +1 -0
- package/dist/chunk-TZKBW4GA.cjs +578 -0
- package/dist/chunk-TZKBW4GA.cjs.map +1 -0
- package/dist/{chunk-47AOS5EC.cjs → chunk-XX6PNPF2.cjs} +60 -2
- package/dist/chunk-XX6PNPF2.cjs.map +1 -0
- package/dist/components/AudioPlayer/index.cjs +7 -6
- package/dist/components/AudioPlayer/index.js +2 -1
- package/dist/components/MediaEditor/index.cjs +10 -9
- package/dist/components/MediaEditor/index.js +5 -4
- package/dist/components/MediaFeed/index.cjs +8 -5
- package/dist/components/MediaFeed/index.d.cts +33 -0
- package/dist/components/MediaFeed/index.d.ts +33 -0
- package/dist/components/MediaFeed/index.js +7 -4
- package/dist/components/MediaPlayer/index.cjs +13 -6
- package/dist/components/MediaPlayer/index.d.cts +103 -5
- package/dist/components/MediaPlayer/index.d.ts +103 -5
- package/dist/components/MediaPlayer/index.js +6 -3
- package/dist/components/Slider/index.cjs +5 -5
- package/dist/components/Slider/index.d.cts +6 -0
- package/dist/components/Slider/index.d.ts +6 -0
- package/dist/components/Slider/index.js +1 -1
- package/dist/components/SliderCalculator/index.cjs +4 -4
- package/dist/components/SliderCalculator/index.js +2 -2
- package/dist/components/SuperChat/index.cjs +16 -14
- package/dist/components/SuperChat/index.cjs.map +1 -1
- package/dist/components/SuperChat/index.d.cts +2 -2
- package/dist/components/SuperChat/index.d.ts +2 -2
- package/dist/components/SuperChat/index.js +8 -6
- package/dist/components/SuperChat/index.js.map +1 -1
- package/dist/components/SuperChat/plugins/index.d.cts +2 -2
- package/dist/components/SuperChat/plugins/index.d.ts +2 -2
- package/dist/hooks/index.cjs +2 -2
- package/dist/hooks/index.js +1 -1
- package/dist/index.cjs +73 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +187 -90
- package/dist/index.d.ts +187 -90
- package/dist/index.js +14 -13
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/tailwind-preset.cjs +4 -4
- package/dist/tailwind-preset.js +1 -1
- package/dist/{types-DSWbrVkM.d.cts → types-BfVolads.d.cts} +33 -0
- package/dist/{types-DSWbrVkM.d.ts → types-BfVolads.d.ts} +33 -0
- package/package.json +1 -1
- package/dist/chunk-47AOS5EC.cjs.map +0 -1
- package/dist/chunk-AIO2GCTL.js.map +0 -1
- package/dist/chunk-ECKIFQSD.cjs +0 -183
- package/dist/chunk-ECKIFQSD.cjs.map +0 -1
- package/dist/chunk-GDKOYVX3.cjs.map +0 -1
- package/dist/chunk-GLXTVCHN.cjs +0 -4
- package/dist/chunk-MNXIN4MS.js.map +0 -1
- package/dist/chunk-OGFSFUIX.cjs.map +0 -1
- package/dist/chunk-QHCAWDMG.cjs.map +0 -1
- package/dist/chunk-R5P7NAJQ.js +0 -159
- package/dist/chunk-R5P7NAJQ.js.map +0 -1
- package/dist/chunk-RISZWWEQ.js +0 -3
- package/dist/chunk-TUYWCUKH.js.map +0 -1
- package/dist/chunk-V5VPECJI.js.map +0 -1
package/agent/README.md
CHANGED
|
@@ -22,7 +22,7 @@ governing spec: later tickets cite it instead of re-deciding.
|
|
|
22
22
|
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
23
|
| [mieweb-ui.instructions.md](mieweb-ui.instructions.md) | The rules template. Copied verbatim to the consumer's `.github/instructions/` (VS Code Copilot auto-applies it via the `applyTo` frontmatter) and embedded, minus frontmatter, in a marked block in the consumer's `AGENTS.md` (the cross-tool convention). |
|
|
24
24
|
| [init-agent.mjs](init-agent.mjs) | The `mieweb-ui` bin. Idempotent — rerun after upgrading `@mieweb/ui` to refresh all targets. `--experimental-agents` additionally installs the agent team below. |
|
|
25
|
-
| [agents/](agents/) | Agent templates: `mieweb-ui-design` (orchestrator) + `mieweb-ui-styling` + `mieweb-ui-install` + `mieweb-ui-a11y` + `mieweb-ui-i18n`. Installed to the consumer's `.github/agents/` behind `--experimental-agents`.
|
|
25
|
+
| [agents/](agents/) | Agent templates: `mieweb-ui-design` (orchestrator) + `mieweb-ui-styling` + `mieweb-ui-install` + `mieweb-ui-a11y` + `mieweb-ui-i18n` + `mieweb-ui-migration`. Installed to the consumer's `.github/agents/` behind `--experimental-agents`. |
|
|
26
26
|
| [skills/](skills/) | Skill templates: `mieweb-ui-catalog`, `mieweb-ui-tokens`, `mieweb-ui-icons` (generated — `pnpm agent:skills`, never hand-edit) + `mieweb-ui-brands`, `mieweb-ui-tailwind4`, `mieweb-ui-a11y-checklist`, `mieweb-ui-i18n-checklist` (hand-written). Installed to `.github/skills/` behind `--experimental-agents`. |
|
|
27
27
|
| `evals/` _(Phase 2+)_ | Golden-question eval sets per specialist; the regression harness for agent knowledge. |
|
|
28
28
|
|
|
@@ -19,6 +19,10 @@ handoffs:
|
|
|
19
19
|
agent: MIE UI i18n Agent
|
|
20
20
|
prompt: Audit the code discussed above for internationalization and RTL compliance (string externalization, locale-bundle completeness, Intl formatting, logical properties) and report findings.
|
|
21
21
|
send: false
|
|
22
|
+
- label: Migration/compliance audit
|
|
23
|
+
agent: MIE UI Migration Agent
|
|
24
|
+
prompt: Audit the code discussed above for @mieweb/ui compliance (raw HTML elements, custom modal/card/badge patterns, hand-rolled icons, CSS foundation) and report findings with a prioritized replacement plan.
|
|
25
|
+
send: false
|
|
22
26
|
---
|
|
23
27
|
|
|
24
28
|
# MIE UI Design Agent (orchestrator)
|
|
@@ -48,14 +52,15 @@ comparison tables) and `mieweb-ui-icons` (icon aliases and conventions):
|
|
|
48
52
|
|
|
49
53
|
## Route to specialists
|
|
50
54
|
|
|
51
|
-
| Question is about… | Delegate to
|
|
52
|
-
| --------------------------------------------------- |
|
|
53
|
-
| install / peer deps / preset / safelist / `@source` | MIE UI Install Agent
|
|
54
|
-
| tokens, CSS vars, Tailwind classes, brands, dark | MIE UI Styling Agent
|
|
55
|
-
| ARIA, keyboard nav, screen readers, contrast | MIE UI A11y Agent
|
|
56
|
-
| translations, locale bundles, Intl formats, RTL | MIE UI i18n Agent
|
|
55
|
+
| Question is about… | Delegate to |
|
|
56
|
+
| --------------------------------------------------- | ---------------------- |
|
|
57
|
+
| install / peer deps / preset / safelist / `@source` | MIE UI Install Agent |
|
|
58
|
+
| tokens, CSS vars, Tailwind classes, brands, dark | MIE UI Styling Agent |
|
|
59
|
+
| ARIA, keyboard nav, screen readers, contrast | MIE UI A11y Agent |
|
|
60
|
+
| translations, locale bundles, Intl formats, RTL | MIE UI i18n Agent |
|
|
61
|
+
| migrating code to @mieweb/ui, raw-HTML compliance | MIE UI Migration Agent |
|
|
57
62
|
|
|
58
|
-
More specialists (
|
|
63
|
+
More specialists (Grids, DataVis, Views,
|
|
59
64
|
SuperChat, Rich Text) land in later phases; until one ships, answer its domain
|
|
60
65
|
from the skills and the component docs, or defer (below).
|
|
61
66
|
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: MIE UI Migration Agent
|
|
3
|
+
description: Migration and compliance auditor for bringing codebases onto @mieweb/ui — raw-HTML-to-component pattern enforcement (badge spans, card divs, raw buttons, tables to DataVis NITRO), hand-rolled SVG to lucide-react, CSS foundation checks, and legacy-framework migration planning (Meteor/Blaze to React). Invoke to audit a file, page, or project for @mieweb/ui compliance or to plan a migration.
|
|
4
|
+
tools: ['search', 'codebase', 'fetch']
|
|
5
|
+
handoffs:
|
|
6
|
+
- label: Apply Fixes
|
|
7
|
+
agent: agent
|
|
8
|
+
prompt: Apply the @mieweb/ui compliance fixes identified in the audit above — replace the flagged raw elements and patterns with the prescribed @mieweb/ui components, preserving existing functionality and event handlers.
|
|
9
|
+
send: false
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MIE UI Migration Agent
|
|
13
|
+
|
|
14
|
+
You are the migration and compliance auditor for the **@mieweb/ui** design
|
|
15
|
+
system. You bring legacy code into compliance: every UI element must use a
|
|
16
|
+
`@mieweb/ui` component when one exists — no raw `<button>`, `<input>`,
|
|
17
|
+
`<select>`, `<table>`, `<textarea>`, or custom modal/card/badge markup. You
|
|
18
|
+
are **read-only**: you audit, plan, and prescribe — the **Apply Fixes**
|
|
19
|
+
handoff performs the edits.
|
|
20
|
+
|
|
21
|
+
## Your sources of truth (never inline-duplicate them)
|
|
22
|
+
|
|
23
|
+
- **`mieweb-ui-catalog` skill** — the component inventory and selection
|
|
24
|
+
guidance; every replacement you prescribe must exist there. It is the
|
|
25
|
+
raw-element → component mapping (`<button>` → `Button`, card divs →
|
|
26
|
+
`Card`/`CardContent`, badge spans → `Badge`, modal divs → `Modal`, …).
|
|
27
|
+
- **`mieweb-ui-tailwind4` skill** — the CSS foundation a migrated project
|
|
28
|
+
needs (`@source` directive, `@custom-variant dark`, `@theme` fallbacks,
|
|
29
|
+
`@tailwindcss/postcss`).
|
|
30
|
+
- **`mieweb-ui-icons` skill** — the lucide-react aliases that replace
|
|
31
|
+
hand-rolled `<svg>` and icon fonts.
|
|
32
|
+
- The installed `mieweb-ui.instructions.md` — the policy you enforce
|
|
33
|
+
(NITRO-first for tables, tokens not hardcoded colors, lucide-react icons).
|
|
34
|
+
|
|
35
|
+
## The prime directive: patterns, not just imports
|
|
36
|
+
|
|
37
|
+
Compliance is not "does the file import @mieweb/ui". Raw HTML that serves
|
|
38
|
+
the same purpose as a component is a violation even when the file already
|
|
39
|
+
imports the library:
|
|
40
|
+
|
|
41
|
+
- `<span className="rounded-full bg-blue-100 px-2 …">` is a `Badge`.
|
|
42
|
+
- `<div className="rounded-lg border p-4 shadow">` is a `Card`.
|
|
43
|
+
- `<div className="fixed inset-0 bg-black/50">…` is a `Modal`.
|
|
44
|
+
- A hand-rolled `<svg>` or icon-font glyph is a `lucide-react` icon.
|
|
45
|
+
- Any `<table>` the user will sort, filter, page, or export is
|
|
46
|
+
**DataVis NITRO** (`Table` only for a few static rows; `AGGrid` is
|
|
47
|
+
deprecated — never migrate _to_ it).
|
|
48
|
+
|
|
49
|
+
## Audit workflow
|
|
50
|
+
|
|
51
|
+
1. **Scope the audit.** A file, a page, or a whole project — confirm which,
|
|
52
|
+
then read the files before reporting. Exclude test files from violation
|
|
53
|
+
counts.
|
|
54
|
+
2. **Grep for raw elements** — `<button`, `<input`, `<select`, `<textarea`,
|
|
55
|
+
`<table`/`<thead`/`<tbody`/`<tr`/`<td`/`<th`, `<form` controls. Also grep
|
|
56
|
+
the **dynamic forms**: literal `type="date"` misses
|
|
57
|
+
`type={cond ? 'date' : 'text'}` — search `type={` and other
|
|
58
|
+
prop-expression variants too.
|
|
59
|
+
3. **Grep for patterns** — badge/pill/tag spans, card-like divs
|
|
60
|
+
(`rounded…border…shadow`), modal/overlay divs (`fixed inset-0`), inline
|
|
61
|
+
`<svg>` and icon-font classes, hand-rolled spinners/progress bars,
|
|
62
|
+
custom tab/breadcrumb/pagination markup.
|
|
63
|
+
4. **Check the CSS foundation** (project-level audits): identify the
|
|
64
|
+
consumer's CSS mode first, then audit against that mode's checklist in
|
|
65
|
+
the `mieweb-ui-tailwind4` skill — Tailwind 4 (`@source` for
|
|
66
|
+
`@mieweb/ui/dist`, `@custom-variant dark`, `@theme` fallbacks,
|
|
67
|
+
`@tailwindcss/postcss`), Tailwind 3 (preset + safelist + `content`
|
|
68
|
+
coverage), or precompiled CSS (`styles.css`/`init.css` import — never
|
|
69
|
+
prescribe Tailwind tooling to it). Validate the dark-mode toggle
|
|
70
|
+
against the `@custom-variant` actually in effect (a single-hook toggle
|
|
71
|
+
against `init.css` is valid); setting both `.dark` and `data-theme` is
|
|
72
|
+
the recommendation for new code, not a violation when one hook matches.
|
|
73
|
+
5. **Build the resolution plan**, prioritized: layout shell (`AppHeader`,
|
|
74
|
+
`Sidebar`, `SiteFooter`) → buttons → form elements → cards & modals →
|
|
75
|
+
tables (NITRO) → feedback (`Badge`, `Toast`, `Spinner`) → navigation
|
|
76
|
+
(`Tabs`, `Breadcrumb`, `Pagination`). Replacements preserve existing
|
|
77
|
+
functionality and event handlers.
|
|
78
|
+
6. **Detect gaps.** A pattern with no `@mieweb/ui` equivalent is not a
|
|
79
|
+
violation — report it with the tier recommendation: compose from existing
|
|
80
|
+
primitives; build locally in library style (CVA variants, `forwardRef`,
|
|
81
|
+
theme CSS variables, dark mode, ARIA); headless-module contract if it
|
|
82
|
+
renders a caller-owned collection; contribute upstream once stable.
|
|
83
|
+
7. **Report, then hand off.** Findings in the format below; offer
|
|
84
|
+
**Apply Fixes** for the edits.
|
|
85
|
+
|
|
86
|
+
## Audit output format
|
|
87
|
+
|
|
88
|
+
### 🧭 @mieweb/ui compliance audit for `<scope>`
|
|
89
|
+
|
|
90
|
+
| # | Category | File | Line | Violation | Replacement |
|
|
91
|
+
| --- | -------- | ---- | ---- | --------- | ----------- |
|
|
92
|
+
|
|
93
|
+
Order findings: raw elements, then patterns, then CSS foundation, then gaps.
|
|
94
|
+
After the table, the compliance summary:
|
|
95
|
+
|
|
96
|
+
| Category | Count | Status |
|
|
97
|
+
| ----------------------- | ----- | ------ |
|
|
98
|
+
| Raw `<button>` | X | ❌ |
|
|
99
|
+
| Raw form elements | X | ❌ |
|
|
100
|
+
| Raw `<table>` | X | ❌ |
|
|
101
|
+
| Custom modal/card/badge | X | ❌ |
|
|
102
|
+
| Hand-rolled icons | X | ❌ |
|
|
103
|
+
| CSS foundation | — | ✅/❌ |
|
|
104
|
+
| Gaps (no equivalent) | N | 📝 |
|
|
105
|
+
|
|
106
|
+
Close with what passes, any judgment calls, and the **Apply Fixes** handoff.
|
|
107
|
+
|
|
108
|
+
## Migration planning (beyond single-file audits)
|
|
109
|
+
|
|
110
|
+
For whole-app migrations (e.g. Meteor 2 + Blaze → Meteor 3 + React +
|
|
111
|
+
@mieweb/ui), plan in this order: scaffold → install deps → the three
|
|
112
|
+
critical CSS/PostCSS/Tailwind config files → verify Tailwind renders →
|
|
113
|
+
shared hooks (`useTheme`, `useBrand`) → layout shell → features one at a
|
|
114
|
+
time, auth first → verify dark mode, brand switching, and `tsc --noEmit`.
|
|
115
|
+
Meteor 3 specifics: all methods async, collection ops use `*Async()`
|
|
116
|
+
variants. Verify each migrated feature before starting the next.
|
|
117
|
+
|
|
118
|
+
## Redirects
|
|
119
|
+
|
|
120
|
+
- "Which component should I use?" for new (non-migration) work → **MIE UI
|
|
121
|
+
Design Agent** (your mapping covers replacements; open-ended selection is
|
|
122
|
+
theirs).
|
|
123
|
+
- Broken styling after install, unstyled components, Tailwind wiring →
|
|
124
|
+
**MIE UI Install Agent** (you flag the missing foundation; they debug it).
|
|
125
|
+
- Token/brand/dark-mode policy questions → **MIE UI Styling Agent**.
|
|
126
|
+
- ARIA, keyboard navigation, focus, contrast → **MIE UI A11y Agent** (your
|
|
127
|
+
replacements inherit library a11y; auditing what remains is theirs).
|
|
128
|
+
- String externalization, locale bundles, RTL → **MIE UI i18n Agent**.
|
|
129
|
+
|
|
130
|
+
## Rules
|
|
131
|
+
|
|
132
|
+
1. Evidence over checklists: cite file and line for every finding; read the
|
|
133
|
+
code before flagging it.
|
|
134
|
+
2. **Patterns, not just imports** — a compliant import list proves nothing;
|
|
135
|
+
grep for the raw markup the components replace.
|
|
136
|
+
3. Grep dynamic forms: prop expressions (`type={…}`, spread props,
|
|
137
|
+
conditional classes) hide violations that literal-string greps miss.
|
|
138
|
+
4. Never prescribe a component or prop you cannot verify in the catalog
|
|
139
|
+
skill, the published component docs (https://ui.mieweb.org), or the
|
|
140
|
+
package's public types — the catalog is a selection inventory, not an
|
|
141
|
+
API reference; a gap honestly reported beats an invented replacement.
|
|
142
|
+
5. Replacements must preserve behavior — event handlers, controlled state,
|
|
143
|
+
form semantics. Flag any replacement that would change behavior as a
|
|
144
|
+
judgment call instead of silently prescribing it.
|
|
@@ -7,7 +7,7 @@ description: Component inventory and selection guidance for the @mieweb/ui desig
|
|
|
7
7
|
|
|
8
8
|
# @mieweb/ui component catalog
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
274 cataloged components. Full docs: https://ui.mieweb.org/ (Storybook; sidebar is Tier / Family / Component, every family has an Overview page).
|
|
11
11
|
|
|
12
12
|
For per-component "Which one?" comparison tables, read [selection-guidance.md](./selection-guidance.md) in this skill and jump to the family's section.
|
|
13
13
|
|
|
@@ -43,7 +43,7 @@ For per-component "Which one?" comparison tables, read [selection-guidance.md](.
|
|
|
43
43
|
|
|
44
44
|
## Inventory
|
|
45
45
|
|
|
46
|
-
Components by tier and family. Annotations: maturity when not stable,
|
|
46
|
+
Components by tier and family. Annotations: maturity when not stable, the import entry when it is not the root (e.g. _(`/datavis`)_), and _(not exported yet)_ for components documented in Storybook but not yet importable — do not recommend those for use.
|
|
47
47
|
|
|
48
48
|
### Foundations
|
|
49
49
|
|
|
@@ -73,14 +73,14 @@ Components by tier and family. Annotations: maturity when not stable, and the im
|
|
|
73
73
|
|
|
74
74
|
- **Chat:** AIChat, AIChat (Voice), AIMessage, ChatComposer _(beta)_, Composer Action Ribbon (POC) _(experimental)_, ComposerModelSelector, MCPToolCall, Messaging, OzwellChat, ReconciliationPanel
|
|
75
75
|
- **Dashboards:** CustomizableDashboard, Dashboard (Demo) _(experimental)_, Dashboard Widgets (Demo) _(experimental)_, DashboardCustomizePanel, DashboardWidget, QuickLinksCard, ReportDashboard
|
|
76
|
-
- **Editors:** EmailEditor _(experimental)_, MacroLibrary _(experimental)_, Markdown, Q _(`/q`)_, RichEditor _(`/kerebron`)_, RichTextEditor, TextAreaRich _(experimental)_
|
|
76
|
+
- **Editors:** EmailEditor _(experimental)_, MacroLibrary _(experimental)_, Markdown, Q _(`/q`)_, RichEditor _(`/kerebron`)_, RichTextEditor, RichTextEsheet _(experimental, `/esheet`)_, TextAreaRich (Kerebron) _(experimental, `/kerebron`)_
|
|
77
77
|
- **Files:** DocumentScanner, DropzoneOverlay, FileManager
|
|
78
78
|
- **Media:** AudioPlayer, AudioRecorder, DictationButton _(experimental)_, MediaEditor, MediaEditor Live Demo, MediaFeed _(experimental, `/components/MediaFeed`)_, MediaPlayer, RecordButton, TranscriptView, VideoCard _(experimental)_
|
|
79
79
|
- **Presentations:** Deck _(experimental, `/deck`)_, PointMap _(experimental, `/maps`)_
|
|
80
80
|
- **Records:** ActionPlan _(experimental)_, ActivityFeed _(experimental)_, AssociationList _(experimental)_, FieldHistory _(experimental)_, OrgChart _(experimental, `/org-chart`)_, RecordLayout _(experimental)_
|
|
81
81
|
- **SuperChat:** Conversations (List) _(`/components/SuperChat`)_, Inbox _(`/components/SuperChat`)_, SuperChat (Panel) _(`/components/SuperChat`)_
|
|
82
82
|
- **Views:** BoardView _(alpha)_, CalendarView _(alpha)_, GanttView _(alpha)_, ListView _(alpha)_, ViewSet _(alpha)_, ViewSwitcher _(alpha)_
|
|
83
|
-
- **Voice:** Hands-Free Chat, Hey Ozwell Demo, Hey Ozwell Selector _(experimental)_, Speaker Verify _(experimental)_, Transcript Player _(experimental)_, Visit Scribe, Voice Manager, Voice Setup, Wake Word
|
|
83
|
+
- **Voice:** Hands-Free Chat, Hey Ozwell Demo, Hey Ozwell Selector _(experimental)_, Speaker Scribe _(experimental, not exported yet)_, Speaker Verify _(experimental)_, Transcript Player _(experimental)_, Visit Scribe, Voice Manager, Voice Setup, Wake Word
|
|
84
84
|
|
|
85
85
|
### Templates
|
|
86
86
|
|
|
@@ -107,7 +107,7 @@ Components by tier and family. Annotations: maturity when not stable, and the im
|
|
|
107
107
|
|
|
108
108
|
### Deprecated
|
|
109
109
|
|
|
110
|
-
- AGGrid _(deprecated, `/ag-grid`)_, AGGrid Enhanced _(deprecated, `/ag-grid`)_
|
|
110
|
+
- AGGrid _(deprecated, `/ag-grid`)_, AGGrid Enhanced _(deprecated, `/ag-grid`)_, TextAreaRich (Legacy) _(deprecated)_
|
|
111
111
|
|
|
112
112
|
## Family policies
|
|
113
113
|
|
|
@@ -198,7 +198,9 @@ The one-line rule that governs each family. When a task touches a family, read i
|
|
|
198
198
|
|
|
199
199
|
> **What is the stored format, and who edits it?** Markdown that people write (and maybe
|
|
200
200
|
> co-write) → `RichEditor`. HTML for templated letters with merge fields and dictation →
|
|
201
|
-
> `RichTextEditor`.
|
|
201
|
+
> `RichTextEditor`. A **multi-section guided document** — referral letters, support tickets —
|
|
202
|
+
> where an eSheet definition supplies the sections and memory aids → `RichTextEsheet`.
|
|
203
|
+
> HTML in a surface that should look like a plain textarea until asked →
|
|
202
204
|
> `TextAreaRich`. An **email** laid out from blocks and compiled to MJML → `EmailEditor`.
|
|
203
205
|
> Markdown that is only **read** → `MarkdownRenderer`. A structured agent
|
|
204
206
|
> configuration with a YAML/JSON pane → `Q`. Plain text storage with rich composing →
|
|
@@ -259,7 +259,9 @@ lists of options in [Choice inputs](https://ui.mieweb.org/?path=/docs/inputs-cho
|
|
|
259
259
|
|
|
260
260
|
> **What is the stored format, and who edits it?** Markdown that people write (and maybe
|
|
261
261
|
> co-write) → `RichEditor`. HTML for templated letters with merge fields and dictation →
|
|
262
|
-
> `RichTextEditor`.
|
|
262
|
+
> `RichTextEditor`. A **multi-section guided document** — referral letters, support tickets —
|
|
263
|
+
> where an eSheet definition supplies the sections and memory aids → `RichTextEsheet`.
|
|
264
|
+
> HTML in a surface that should look like a plain textarea until asked →
|
|
263
265
|
> `TextAreaRich`. An **email** laid out from blocks and compiled to MJML → `EmailEditor`.
|
|
264
266
|
> Markdown that is only **read** → `MarkdownRenderer`. A structured agent
|
|
265
267
|
> configuration with a YAML/JSON pane → `Q`. Plain text storage with rich composing →
|
|
@@ -272,10 +274,12 @@ lists of options in [Choice inputs](https://ui.mieweb.org/?path=/docs/inputs-cho
|
|
|
272
274
|
| --- | --- | --- |
|
|
273
275
|
| [RichEditor](https://ui.mieweb.org/?path=/docs/editors-richeditor--docs) | The document is **Markdown**: headings, lists, tables, code; `getContent()` on submit; `collab.room` for Yjs co-editing; `CodeEditor` for source | The stored format is HTML or you need merge variables/dictation — `RichTextEditor`; the host cannot add the Kerebron peers and WASM assets |
|
|
274
276
|
| [RichTextEditor](https://ui.mieweb.org/?path=/docs/editors-richtexteditor--docs) | The document is **HTML**: bold/italic/underline, lists, alignment, opt-in markdown block shortcuts (H1–H3, lists, quote), `variableGroups` inserting `{{tokens}}`, Web Speech dictation; no peers | You need Markdown, real undo history, links/tables/code or collaboration — `RichEditor`; plain text — `Textarea`; a textarea-like surface with the toolbar hidden — `TextAreaRich` |
|
|
275
|
-
| [TextAreaRich](https://ui.mieweb.org/?path=/docs/editors-textarearich--docs) | A **textarea-like** HTML surface: starts one Input row tall and auto-grows, toolbar hidden until asked, markdown block shortcuts, a Notion-style `+` gutter menu, `.shortcut` macros | The value must be **plain text** (form posts, bindings) — `Textarea` (this surface with a plain-text contract); a full document with an always-on toolbar, variables or dictation — `RichTextEditor` |
|
|
277
|
+
| [TextAreaRich](https://ui.mieweb.org/?path=/docs/editors-textarearich-kerebron--docs) | A **textarea-like** HTML surface on the Kerebron engine (`@mieweb/ui/kerebron`): starts one Input row tall and auto-grows, toolbar hidden until asked, markdown block shortcuts, a Notion-style `+` gutter menu, `.shortcut` macros | The value must be **plain text** (form posts, bindings) — `Textarea` (this surface with a plain-text contract); a full document with an always-on toolbar, variables or dictation — `RichTextEditor` |
|
|
278
|
+
| [RichTextEsheet](https://ui.mieweb.org/?path=/docs/editors-richtextesheet--docs) | A **multi-section guided document** — referral letters, support tickets, incident write-ups — where an eSheet definition drives section prompts, memory-aid phrases and party macros; exports portable MDY | One free-form HTML letter with merge fields and dictation — `RichTextEditor`; a single rich input — `TextAreaRich`; arbitrary native `FormDefinition` forms — EsheetRenderer (Composite forms); coded clinical visits — EncounterVisit (Encounter & orders) |
|
|
276
279
|
| [EmailEditor](https://ui.mieweb.org/?path=/docs/editors-emaileditor--docs) | The document is an **email**: hero, columns, buttons, images, social, footer blocks on a drag-to-reorder canvas; `renderEmailMjml` serialises it | A single formatted body — `RichTextEditor`; sending, recipients and templates are the host's |
|
|
277
280
|
| [Markdown](https://ui.mieweb.org/?path=/docs/editors-markdown--docs) | **Displaying** Markdown: sanitised HTML, code highlighting, `mermaid` / `csv` / `survey` / `html` fences, `streaming` for token-by-token AI output | The user edits the text — `RichEditor` / `RichTextEditor`; the source is HTML |
|
|
278
281
|
| [Q](https://ui.mieweb.org/?path=/docs/editors-q--docs) | Admins configure an **agent** (prompt, tools, telephony) through a schema-generated form and see the YAML/JSON; `onSubmit(yaml)`, `onConfigChange` | Free-form prose — `RichEditor`; general clinical/business forms — ESheet (Composite forms) |
|
|
282
|
+
| [TextAreaRich (Legacy)](https://ui.mieweb.org/?path=/docs/deprecated-textarearich--docs) _(deprecated)_ | Never for new work — the `document.execCommand` engine; use [TextAreaRich (Kerebron)](https://ui.mieweb.org/?path=/docs/editors-textarearich-kerebron--docs) | — |
|
|
279
283
|
|
|
280
284
|
---
|
|
281
285
|
|
|
@@ -432,8 +436,8 @@ Related, in other families: `Button isLoading` (inline spinner), `ReadingProgres
|
|
|
432
436
|
| Component | Use it when | Not when |
|
|
433
437
|
| --- | --- | --- |
|
|
434
438
|
| [AudioPlayer](https://ui.mieweb.org/?path=/docs/media-audioplayer--docs) | A small, themed player for one audio clip: `inline` / `compact` / `waveform` variants, `AudioPlayerRef` in **seconds**, `preload={false}` for lists | The source may be video or you want native controls and captions — `MediaPlayer`; you are capturing — `AudioRecorder` / `RecordButton` |
|
|
435
|
-
| [MediaPlayer](https://ui.mieweb.org/?path=/docs/media-mediaplayer--docs) |
|
|
436
|
-
| [MediaFeed](https://ui.mieweb.org/?path=/docs/media-mediafeed--docs) | A host-owned collection of clips and images with vertical browsing, one active player and an immersive viewer; also the media view of [SuperChatInbox](https://ui.mieweb.org/?path=/docs/superchat-inbox--docs) | A single clip — `MediaPlayer`; a linked video thumbnail — `VideoCard`; text discussion — the normal SuperChat thread |
|
|
439
|
+
| [MediaPlayer](https://ui.mieweb.org/?path=/docs/media-mediaplayer--docs) | `<audio>`/`<video>` with the browser's controls or, for video, touch-first overlay controls (`controlsStyle`); `kind` inferred from the extension; `MediaPlayerRef` in **milliseconds** | You want a compact styled audio control or a waveform — `AudioPlayer`; the words are edited — `MediaEditor` |
|
|
440
|
+
| [MediaFeed](https://ui.mieweb.org/?path=/docs/media-mediafeed--docs) | A host-owned collection of clips and images with vertical browsing, one active player and an immersive viewer, as cards or edge to edge (`layout`); also the media view of [SuperChatInbox](https://ui.mieweb.org/?path=/docs/superchat-inbox--docs) | A single clip — `MediaPlayer`; a linked video thumbnail — `VideoCard`; text discussion — the normal SuperChat thread |
|
|
437
441
|
| [TranscriptView](https://ui.mieweb.org/?path=/docs/media-transcriptview--docs) | Read-only word- or segment-level transcript that highlights `currentTimeMs` and reports `onSeek(ms)`; speaker rows via `speakerLabels` / `mergeSameSpeaker` | The user changes words or the cut — `MediaEditor`; you have no media position to follow |
|
|
438
442
|
| [MediaEditor](https://ui.mieweb.org/?path=/docs/media-mediaeditor--docs) | Word-timestamped `Transcript` the user tightens: delete/cut/paste words, split silences, filler removal, speed markers; state persisted via `onEditorStateChange` | Read-only playback — `TranscriptView` + `MediaPlayer`; segment-only timestamps (no per-word times) |
|
|
439
443
|
| [MediaEditor Live Demo](https://ui.mieweb.org/?path=/docs/media-mediaeditor-live-demo--docs) | Trying `MediaEditor` on your own file: on-device Whisper transcription, then the editor with the Script panel | Anything you ship — use `MediaEditor` with your own transcription source |
|
|
@@ -649,7 +653,7 @@ executive summary (numbers as lettermark icons) and outlook, and `LeadFormSectio
|
|
|
649
653
|
| Component | Use it when | Not when |
|
|
650
654
|
| --- | --- | --- |
|
|
651
655
|
| [Input](https://ui.mieweb.org/?path=/docs/text-inputs-input--docs) | One line of free text or a native type (`email`, `password`, `number`) | Phone / URL / date / fixed options — see the specialists |
|
|
652
|
-
| [Textarea](https://ui.mieweb.org/?path=/docs/text-inputs-textarea--docs) | A sentence or more stored as **plain text** — rich formatting while composing ([TextAreaRich](https://ui.mieweb.org/?path=/docs/editors-textarearich--docs) underneath), plain string through `onChange` | The host **persists** HTML — [TextAreaRich](https://ui.mieweb.org/?path=/docs/editors-textarearich--docs); native `<textarea>` behaviours (hard `maxLength`, validation, drag-resize, floating label) — `TextAreaPlain` (documented on the Textarea page); full documents — `RichEditor` / `RichTextEditor` |
|
|
656
|
+
| [Textarea](https://ui.mieweb.org/?path=/docs/text-inputs-textarea--docs) | A sentence or more stored as **plain text** — rich formatting while composing ([TextAreaRich](https://ui.mieweb.org/?path=/docs/editors-textarearich-kerebron--docs) underneath), plain string through `onChange` | The host **persists** HTML — [TextAreaRich (Kerebron)](https://ui.mieweb.org/?path=/docs/editors-textarearich-kerebron--docs); native `<textarea>` behaviours (hard `maxLength`, validation, drag-resize, floating label) — `TextAreaPlain` (documented on the Textarea page); full documents — `RichEditor` / `RichTextEditor` |
|
|
653
657
|
| [Label](https://ui.mieweb.org/?path=/docs/text-inputs-label--docs) | Labelling a control with no `label` prop (raw `<select>`, custom) | The control already takes `label` |
|
|
654
658
|
| [PhoneInput](https://ui.mieweb.org/?path=/docs/text-inputs-phoneinput--docs) | Exactly one US/Canada number stored as 10 digits | Several typed numbers — `PhoneInputGroup`; international |
|
|
655
659
|
| [PhoneInputGroup](https://ui.mieweb.org/?path=/docs/text-inputs-phoneinputgroup--docs) | A record holds several numbers and the type (cell, work, fax) matters | One number; rows need extra fields |
|
|
@@ -72,6 +72,7 @@ function useMediaTransport(options = {}) {
|
|
|
72
72
|
};
|
|
73
73
|
const onDurationChange = () => setDurationMs(toMs(element.duration));
|
|
74
74
|
const onTimeUpdateEvt = () => emitTime();
|
|
75
|
+
const onRateChange = () => setPlaybackRateState(element.playbackRate);
|
|
75
76
|
const onPlay = () => setState("playing");
|
|
76
77
|
const onPlaying = () => setState("playing");
|
|
77
78
|
const onPause = () => setState("paused");
|
|
@@ -94,6 +95,7 @@ function useMediaTransport(options = {}) {
|
|
|
94
95
|
element.addEventListener("loadedmetadata", onLoadedMetadata);
|
|
95
96
|
element.addEventListener("durationchange", onDurationChange);
|
|
96
97
|
element.addEventListener("timeupdate", onTimeUpdateEvt);
|
|
98
|
+
element.addEventListener("ratechange", onRateChange);
|
|
97
99
|
element.addEventListener("play", onPlay);
|
|
98
100
|
element.addEventListener("playing", onPlaying);
|
|
99
101
|
element.addEventListener("pause", onPause);
|
|
@@ -108,6 +110,7 @@ function useMediaTransport(options = {}) {
|
|
|
108
110
|
element.removeEventListener("loadedmetadata", onLoadedMetadata);
|
|
109
111
|
element.removeEventListener("durationchange", onDurationChange);
|
|
110
112
|
element.removeEventListener("timeupdate", onTimeUpdateEvt);
|
|
113
|
+
element.removeEventListener("ratechange", onRateChange);
|
|
111
114
|
element.removeEventListener("play", onPlay);
|
|
112
115
|
element.removeEventListener("playing", onPlaying);
|
|
113
116
|
element.removeEventListener("pause", onPause);
|
|
@@ -127,7 +130,8 @@ function useMediaTransport(options = {}) {
|
|
|
127
130
|
const togglePlay = useCallback(() => {
|
|
128
131
|
const el = elementRef.current;
|
|
129
132
|
if (!el) return;
|
|
130
|
-
if (el.paused) void el.play()
|
|
133
|
+
if (el.paused) void el.play()?.catch(() => {
|
|
134
|
+
});
|
|
131
135
|
else el.pause();
|
|
132
136
|
}, []);
|
|
133
137
|
const seekToMs = useCallback((timeMs) => {
|
|
@@ -171,5 +175,5 @@ function useMediaTransport(options = {}) {
|
|
|
171
175
|
}
|
|
172
176
|
|
|
173
177
|
export { useMediaTransport };
|
|
174
|
-
//# sourceMappingURL=chunk-
|
|
175
|
-
//# sourceMappingURL=chunk-
|
|
178
|
+
//# sourceMappingURL=chunk-4LKAZW2W.js.map
|
|
179
|
+
//# sourceMappingURL=chunk-4LKAZW2W.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useMediaTransport.ts"],"names":[],"mappings":"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","file":"chunk-4LKAZW2W.js","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type MediaTransportState =\n | 'idle'\n | 'loading'\n | 'playing'\n | 'paused'\n | 'error';\n\nexport interface UseMediaTransportOptions {\n /** Fired on every native `timeupdate` and on metadata load, in milliseconds. */\n onTimeUpdate?: (currentTimeMs: number, durationMs: number) => void;\n /** Fired whenever the derived transport state changes. */\n onStateChange?: (state: MediaTransportState) => void;\n /** Fired when playback reaches the end. */\n onEnded?: () => void;\n /** Fired on a media error, with a descriptive Error. */\n onError?: (error: Error) => void;\n /** Initial playback rate (default `1`). Kept in sync with the element. */\n initialRate?: number;\n /** Transport state to enter when playback ends (default `'paused'`). */\n endedState?: Extract<MediaTransportState, 'idle' | 'paused'>;\n /** Reset the position to `0` when playback ends (default `false`). */\n resetTimeOnEnd?: boolean;\n /** Human-readable label used in the error message (default `'media'`). */\n errorLabel?: string;\n}\n\nexport interface UseMediaTransportReturn {\n /**\n * Callback ref for the `<audio>`/`<video>` element to control. Pass this to\n * the element's `ref` (or call it imperatively). Transport listeners attach\n * when an element mounts and detach when it unmounts.\n */\n setMediaElement: (element: HTMLMediaElement | null) => void;\n /** The currently attached media element, or `null`. */\n mediaElement: HTMLMediaElement | null;\n\n /** Derived transport state. */\n state: MediaTransportState;\n /** Current playback position in milliseconds. */\n currentTimeMs: number;\n /** Media duration in milliseconds (`0` until known / non-finite). */\n durationMs: number;\n /** Current playback rate. */\n playbackRate: number;\n /** `true` while `state === 'playing'`. */\n isPlaying: boolean;\n /** `true` while `state === 'loading'`. */\n isLoading: boolean;\n\n /** Start playback. */\n play: () => void;\n /** Pause playback. */\n pause: () => void;\n /** Toggle between play and pause. */\n togglePlay: () => void;\n /** Seek to a position in milliseconds. */\n seekToMs: (timeMs: number) => void;\n /** Set the playback rate multiplier. */\n setPlaybackRate: (rate: number) => void;\n /** Read the current position in milliseconds. */\n getCurrentTimeMs: () => number;\n /** Read the duration in milliseconds (`0` when unknown). */\n getDurationMs: () => number;\n /** Whether playback is currently paused (reads the element directly). */\n isPaused: () => boolean;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nconst toMs = (seconds: number): number =>\n Number.isFinite(seconds) ? seconds * 1000 : 0;\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Headless playback transport for a native `HTMLMediaElement`.\n *\n * Owns the derived transport state (idle/loading/playing/paused/error),\n * position, duration and playback rate, and exposes imperative controls — all\n * in **milliseconds**. It never creates or renders an element: pass the\n * returned {@link UseMediaTransportReturn.setMediaElement} callback to an\n * `<audio>`/`<video>` `ref` and the hook wires the native listeners.\n *\n * Shared by `MediaPlayer` (ms API) and TranscriptPlayer's `usePlayback` (seconds,\n * converted at the boundary). The WaveSurfer waveform variant is\n * out of scope; this hook targets native media transport only.\n *\n * @example\n * ```tsx\n * function Player({ src }: { src: string }) {\n * const t = useMediaTransport({ onEnded: () => console.log('done') });\n * return (\n * <div>\n * <video ref={t.setMediaElement} src={src} controls />\n * <button onClick={t.togglePlay}>{t.isPlaying ? 'Pause' : 'Play'}</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useMediaTransport(\n options: UseMediaTransportOptions = {}\n): UseMediaTransportReturn {\n const {\n onTimeUpdate,\n onStateChange,\n onEnded,\n onError,\n initialRate = 1,\n endedState = 'paused',\n resetTimeOnEnd = false,\n errorLabel = 'media',\n } = options;\n\n const [element, setElementState] = useState<HTMLMediaElement | null>(null);\n const [state, setStateRaw] = useState<MediaTransportState>('idle');\n const stateRef = useRef<MediaTransportState>('idle');\n const [currentTimeMs, setCurrentTimeMs] = useState(0);\n const [durationMs, setDurationMs] = useState(0);\n const [playbackRate, setPlaybackRateState] = useState(initialRate);\n\n const elementRef = useRef<HTMLMediaElement | null>(null);\n\n // Keep the latest callbacks/options in a ref so the listener effect does not\n // re-subscribe on every render when callers pass inline functions.\n const handlers = useRef({\n onTimeUpdate,\n onStateChange,\n onEnded,\n onError,\n endedState,\n resetTimeOnEnd,\n errorLabel,\n });\n handlers.current = {\n onTimeUpdate,\n onStateChange,\n onEnded,\n onError,\n endedState,\n resetTimeOnEnd,\n errorLabel,\n };\n\n const setState = useCallback((next: MediaTransportState) => {\n if (stateRef.current === next) return;\n stateRef.current = next;\n setStateRaw(next);\n // Consumers often update parent state here. Keep that notification outside\n // React's state updater, which may run during render or twice in StrictMode.\n handlers.current.onStateChange?.(next);\n }, []);\n\n const setMediaElement = useCallback((el: HTMLMediaElement | null) => {\n elementRef.current = el;\n setElementState(el);\n }, []);\n\n // Attach native transport listeners whenever an element mounts.\n useEffect(() => {\n if (!element) {\n // A detached element (e.g. the source was removed) leaves nothing playing or loaded;\n // an error stays visible to hosts that swap the element for an error panel.\n if (stateRef.current !== 'error') setState('idle');\n setDurationMs(0);\n setCurrentTimeMs(0);\n return;\n }\n\n const emitTime = () => {\n const ms = toMs(element.currentTime);\n const dur = toMs(element.duration);\n setCurrentTimeMs(ms);\n handlers.current.onTimeUpdate?.(ms, dur);\n };\n\n const onLoadStart = () => setState('loading');\n // canplay can also follow a seek mid-playback; only leave the loading state here.\n const onCanPlay = () => {\n if (stateRef.current === 'loading')\n setState(element.paused ? 'idle' : 'playing');\n };\n const onLoadedMetadata = () => {\n setDurationMs(toMs(element.duration));\n emitTime();\n };\n // MediaRecorder webm often reports Infinity until the end is known.\n const onDurationChange = () => setDurationMs(toMs(element.duration));\n const onTimeUpdateEvt = () => emitTime();\n // The speed can change outside these controls (iOS's own full screen player).\n const onRateChange = () => setPlaybackRateState(element.playbackRate);\n const onPlay = () => setState('playing');\n const onPlaying = () => setState('playing');\n const onPause = () => setState('paused');\n const onEndedEvt = () => {\n setState(handlers.current.endedState);\n if (handlers.current.resetTimeOnEnd) {\n element.currentTime = 0;\n setCurrentTimeMs(0);\n }\n handlers.current.onEnded?.();\n };\n const onErrorEvt = () => {\n setState('error');\n handlers.current.onError?.(\n new Error(`Failed to load ${handlers.current.errorLabel}`)\n );\n };\n\n element.addEventListener('loadstart', onLoadStart);\n element.addEventListener('canplay', onCanPlay);\n element.addEventListener('loadedmetadata', onLoadedMetadata);\n element.addEventListener('durationchange', onDurationChange);\n element.addEventListener('timeupdate', onTimeUpdateEvt);\n element.addEventListener('ratechange', onRateChange);\n element.addEventListener('play', onPlay);\n element.addEventListener('playing', onPlaying);\n element.addEventListener('pause', onPause);\n element.addEventListener('ended', onEndedEvt);\n element.addEventListener('error', onErrorEvt);\n\n // Sync on attach; a new element must not inherit the previous one's duration or play state.\n setDurationMs(toMs(element.duration));\n if (element.paused && stateRef.current === 'playing') setState('paused');\n // e.g. a 404 that failed before hydration attached these listeners.\n if (element.error) onErrorEvt();\n\n return () => {\n element.removeEventListener('loadstart', onLoadStart);\n element.removeEventListener('canplay', onCanPlay);\n element.removeEventListener('loadedmetadata', onLoadedMetadata);\n element.removeEventListener('durationchange', onDurationChange);\n element.removeEventListener('timeupdate', onTimeUpdateEvt);\n element.removeEventListener('ratechange', onRateChange);\n element.removeEventListener('play', onPlay);\n element.removeEventListener('playing', onPlaying);\n element.removeEventListener('pause', onPause);\n element.removeEventListener('ended', onEndedEvt);\n element.removeEventListener('error', onErrorEvt);\n };\n }, [element, setState]);\n\n // Keep the element's playback rate in sync with hook state.\n useEffect(() => {\n if (element) element.playbackRate = playbackRate;\n }, [element, playbackRate]);\n\n const play = useCallback(() => {\n void elementRef.current?.play();\n }, []);\n\n const pause = useCallback(() => {\n elementRef.current?.pause();\n }, []);\n\n const togglePlay = useCallback(() => {\n const el = elementRef.current;\n if (!el) return;\n // A refused start (autoplay policy) leaves it paused; nothing to report.\n if (el.paused) void el.play()?.catch(() => {});\n else el.pause();\n }, []);\n\n const seekToMs = useCallback((timeMs: number) => {\n const el = elementRef.current;\n if (el) {\n el.currentTime = timeMs / 1000;\n setCurrentTimeMs(timeMs);\n }\n }, []);\n\n const setPlaybackRate = useCallback((rate: number) => {\n setPlaybackRateState(rate);\n if (elementRef.current) elementRef.current.playbackRate = rate;\n }, []);\n\n const getCurrentTimeMs = useCallback(\n () => toMs(elementRef.current?.currentTime ?? 0),\n []\n );\n\n const getDurationMs = useCallback(\n () => toMs(elementRef.current?.duration ?? 0),\n []\n );\n\n const isPaused = useCallback(() => elementRef.current?.paused ?? true, []);\n\n return {\n setMediaElement,\n mediaElement: element,\n state,\n currentTimeMs,\n durationMs,\n playbackRate,\n isPlaying: state === 'playing',\n isLoading: state === 'loading',\n play,\n pause,\n togglePlay,\n seekToMs,\n setPlaybackRate,\n getCurrentTimeMs,\n getDurationMs,\n isPaused,\n };\n}\n"]}
|
|
@@ -87,6 +87,64 @@ var miewebUISafelist = [
|
|
|
87
87
|
// MediaFeed vertical snapping, bounded captions, fullscreen viewport and
|
|
88
88
|
// SuperChat attachment previews for consumers that do not scan package code.
|
|
89
89
|
"h-[min(48rem,80dvh)]",
|
|
90
|
+
// MediaPlayer overlay controls and MediaFeed's overlay layout: scrims,
|
|
91
|
+
// round overlay buttons, pointer-aware sizes and the narrow-player
|
|
92
|
+
// container query and pointer variants (these need Tailwind 4.1).
|
|
93
|
+
"@container",
|
|
94
|
+
"w-fit",
|
|
95
|
+
// Previous/Next at the top end on a short screen (a phone held sideways).
|
|
96
|
+
"[@media(max-height:30rem)]:top-2",
|
|
97
|
+
"[@media(max-height:30rem)]:translate-y-0",
|
|
98
|
+
"via-black/30",
|
|
99
|
+
"pb-3",
|
|
100
|
+
"max-w-xl",
|
|
101
|
+
"px-14",
|
|
102
|
+
"dark:bg-white/30",
|
|
103
|
+
"@max-md:basis-full",
|
|
104
|
+
"@max-md:me-auto",
|
|
105
|
+
"@max-md:mx-2",
|
|
106
|
+
"@max-md:order-first",
|
|
107
|
+
"@max-xs:hidden",
|
|
108
|
+
"@max-xs:pt-2",
|
|
109
|
+
"[text-shadow:0_1px_2px_rgb(0_0_0/0.6)]",
|
|
110
|
+
"active:bg-black/75",
|
|
111
|
+
"backdrop-blur-sm",
|
|
112
|
+
"bg-black",
|
|
113
|
+
"bg-black/45",
|
|
114
|
+
"bg-gradient-to-b",
|
|
115
|
+
"dark:active:bg-black/75",
|
|
116
|
+
"dark:hover:bg-black/65",
|
|
117
|
+
"fill-current",
|
|
118
|
+
"focus-visible:-outline-offset-2",
|
|
119
|
+
"focus-visible:outline-2",
|
|
120
|
+
"focus-visible:outline-white/70",
|
|
121
|
+
"focus-visible:ring-offset-0",
|
|
122
|
+
"focus-visible:ring-white",
|
|
123
|
+
"from-black/75",
|
|
124
|
+
"from-black/55",
|
|
125
|
+
"via-black/55",
|
|
126
|
+
"gap-x-1",
|
|
127
|
+
"hover:bg-black/65",
|
|
128
|
+
"leading-5",
|
|
129
|
+
"mx-1",
|
|
130
|
+
"pb-10",
|
|
131
|
+
"pointer-coarse:[&_[data-slot=slider-track-wrapper]]:py-4",
|
|
132
|
+
"pointer-events-auto",
|
|
133
|
+
"pointer-fine:h-14",
|
|
134
|
+
"pointer-fine:h-9",
|
|
135
|
+
"pointer-fine:w-14",
|
|
136
|
+
"pointer-fine:w-9",
|
|
137
|
+
"sm:px-2",
|
|
138
|
+
"snap-always",
|
|
139
|
+
"via-black/40",
|
|
140
|
+
"[&_[data-slot=media-controls-bar]]:bg-none",
|
|
141
|
+
"[&_[data-slot=media-controls-bar]]:bg-black/55",
|
|
142
|
+
"pt-16",
|
|
143
|
+
"ring-white/70",
|
|
144
|
+
"self-stretch",
|
|
145
|
+
// MediaPlayer's box with the browser's controls: the video lays out as
|
|
146
|
+
// if it weren't there.
|
|
147
|
+
"contents",
|
|
90
148
|
"h-dvh",
|
|
91
149
|
"sm:h-[calc(100dvh-2rem)]",
|
|
92
150
|
"max-h-[40%]",
|
|
@@ -1919,5 +1977,5 @@ var miewebUIPreset = {
|
|
|
1919
1977
|
var tailwind_preset_default = miewebUIPreset;
|
|
1920
1978
|
|
|
1921
1979
|
export { miewebUIPreset, miewebUISafelist, tailwind_preset_default };
|
|
1922
|
-
//# sourceMappingURL=chunk-
|
|
1923
|
-
//# sourceMappingURL=chunk-
|
|
1980
|
+
//# sourceMappingURL=chunk-5WA6IYZD.js.map
|
|
1981
|
+
//# sourceMappingURL=chunk-5WA6IYZD.js.map
|