|
| 1 | +# apps/editor |
| 2 | + |
| 3 | +Vanilla TypeScript + DOM event editor (no framework). `main.ts` bundles |
| 4 | +via esbuild to `dist/main.js`; `index.html`/`styles.css` are static files |
| 5 | +copied into `dist/`. |
| 6 | + |
| 7 | +## Dev workflow gotcha |
| 8 | + |
| 9 | +`pnpm dev` (esbuild watch + static server) only rebuilds `dist/main.js` |
| 10 | +on save. `index.html` and `styles.css` are copied into `dist/` **once**, |
| 11 | +at server startup — they are not watched. After editing either, run: |
| 12 | + |
| 13 | + cp apps/editor/index.html apps/editor/styles.css apps/editor/dist/ |
| 14 | + |
| 15 | +before reloading the browser, or you'll be looking at stale markup/CSS. |
| 16 | + |
| 17 | +## CSS: the `hidden` attribute loses to author `display` rules |
| 18 | + |
| 19 | +Any CSS rule that sets `display:` on a selector that's *also* toggled via |
| 20 | +the JS `hidden` property must be scoped `:not([hidden])`. An author |
| 21 | +stylesheet rule always wins over the UA stylesheet's `[hidden] { display: |
| 22 | +none }`, regardless of specificity — so a plain `.foo { display: flex }` |
| 23 | +silently defeats `fooEl.hidden = true` elsewhere. Bitten by this |
| 24 | +repeatedly in the same session: `#profile-switch`, `.recurrence-fields`, |
| 25 | +`.field.pair`. When adding a new `display:` rule on anything toggled by |
| 26 | +`.hidden = …` in `main.ts`/`ui/form.ts`, default to `:not([hidden])`. |
| 27 | + |
| 28 | +## Native date/time inputs have a rendering-width floor |
| 29 | + |
| 30 | +`<input type="date">`/`<input type="time">` won't shrink below their own |
| 31 | +intrinsic minimum width in Chrome, regardless of `flex-basis`/`width` |
| 32 | +CSS. Cramming 4-5 of them into a narrow flex row (e.g. inside a |
| 33 | +`.repeater-item`) may still wrap even with generous CSS budgeting — a |
| 34 | +real platform constraint, not a CSS bug worth chasing further. |
| 35 | + |
| 36 | +## Browser-testing this app: avoid getting stuck on confirm()/beforeunload |
| 37 | + |
| 38 | +The app calls `window.confirm(...)` before discarding a pending import |
| 39 | +queue or replacing form content, and has a `beforeunload` handler |
| 40 | +guarding unsaved changes. Both are **native browser dialogs** — triggering |
| 41 | +one via the `computer` tool's click action blocks the whole |
| 42 | +Claude-in-Chrome session (CDP calls time out) until dismissed. |
| 43 | +- Before clicking anything that might trigger a confirm(), stub it first |
| 44 | + via `javascript_tool`: `window.confirm = () => true;` |
| 45 | +- If a `beforeunload` "Leave site?" dialog gets stuck anyway, recover by |
| 46 | + calling `navigate` again with `force: true` — it discards the dialog |
| 47 | + and proceeds. |
| 48 | + |
| 49 | +## OTE has no recurrence-rule concept |
| 50 | + |
| 51 | +The spec is explicit: one document per occurrence, always ("un documento |
| 52 | += una ocurrencia. Quien publica expande."). Never store a rule in an |
| 53 | +event/feed file — a "repeat" feature must *generate* N documents, not |
| 54 | +represent recurrence as data. The spec's own guidance for an otherwise |
| 55 | +open-ended series: expand a bounded horizon ("12 meses o las próximas 12 |
| 56 | +ocurrencias"), not forever — `lib/recurrence.ts`'s `MAX_OCCURRENCES` caps |
| 57 | +every generated series at 24 for this reason. |
0 commit comments