Commit graph

10 commits

Author SHA1 Message Date
Claude
32be92fa24
Add declarative data-modal-cancel attribute to datasette-modal
Clicking any element inside a <datasette-modal> that carries a
data-modal-cancel attribute now calls requestClose("cancel"), so
Cancel buttons no longer need JavaScript wiring. Like other
dismissals this respects the busy property and the closeGuard hook.

The set-column-type, row-delete and create-table dialogs now use the
attribute instead of their own click listeners, and the plugin
documentation example is simplified to match (the regenerated docs
screenshot is unchanged).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TShiUYVMmmF4zyJR6GMw34
2026-07-02 17:25:19 +00:00
Claude
967c1298ea
Add script to regenerate the datasette-modal docs screenshot
docs/generate-datasette-modal-example.sh builds a temporary demo
database and plugins directory containing the createModal() example
from the Modal dialogs documentation, starts a Datasette server, takes
the screenshot with shot-scraper, quantizes it to an 8-bit palette PNG
and stops the server again. Output is byte-identical to the committed
docs/datasette-modal-example.png.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TShiUYVMmmF4zyJR6GMw34
2026-07-02 16:19:37 +00:00
Claude
5fd27d9347
Add screenshot of the datasette-modal example to the docs
Taken with shot-scraper against a local Datasette instance running the
createModal() example plugin code from the Modal dialogs docs section,
then palette-quantized to keep the file size down (87KB at 1520x920).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TShiUYVMmmF4zyJR6GMw34
2026-07-02 16:16:15 +00:00
Claude
0693f2f099
Extract shared datasette-modal web component for all modal dialogs
All eight modal dialogs (create table, alter table, insert/edit row,
delete row, set column type, column chooser, mobile column actions and
the navigation jump menu) previously each implemented their own <dialog>
creation, header/footer markup, backdrop-click and Escape handling,
busy-state guards, focus restoration and near-identical frame CSS.

This extracts all of that into a new <datasette-modal> web component
(datasette/static/datasette-modal.js) that wraps a native <dialog> and
provides:

- The standard modal frame, header (title + meta chip), footer and
  button styles, distributed via a stylesheet adopted into whichever
  document or shadow root the element is connected to - so it also
  works inside the shadow DOM of column-chooser and navigation-search
- Close on backdrop click and Escape, a busy property that blocks
  dismissal during saves, and a closeGuard hook for discard-changes
  confirmation prompts
- Focus restoration to the triggering element on close
- datasette-modal-open and datasette-modal-close events
- Per-dialog sizing via --datasette-modal-width /
  --datasette-modal-max-height custom properties

The component is exposed as window.DatasetteModal and via a new
datasetteManager.createModal() method, and is documented in
docs/javascript_plugins.rst as a stable public API for plugins.

This removes roughly 1,200 lines of duplicated frame markup, event
wiring and CSS across table.js, edit-tools.js, mobile-column-actions.js,
column-chooser.js, navigation-search.js and app.css, while keeping the
existing dialog ids, class names and inner structure intact.

Also adds Playwright coverage for the column chooser, mobile column
actions and set-column-type dialogs, which previously had none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TShiUYVMmmF4zyJR6GMw34
2026-07-02 16:01:36 +00:00
Simon Willison
bba7e0b027 Better docs for makeJumpSections()
Closes #2778
2026-06-14 16:28:09 -07:00
Simon Willison
3f7d389caf Refine column field plugin API and documentation
- Simplify JavaScript column field context:
  - expose `isPk` instead of `isPrimaryKey`
  - expose `defaultExpression` instead of separate SQLite default flags
  - remove value/default state from plugin context
- Update field helper behavior:
  - `setValue()` no longer dispatches input/change events
  - remove dispatch options and `resetValue()`
  - add `markClean()` for plugin-normalized initial values
  - track clean field state for reliable dirty detection

Also:

- Prompt before closing row insert/edit dialogs when there are unsaved changes
- Map declared SQLite types to affinities, returning `BLOB` for typeless columns and `NUMERIC` for numeric/date/boolean-like declarations
2026-06-14 15:09:24 -07:00
Simon Willison
841a2536ea Tighten row edit field plugin API
Replace the value/valueType/originalValue/originalValueType fields on makeColumnField() contexts with an explicit field object API for reading, writing, resetting, comparing and validating field values.

Normalize columnType to {type, config}, rename the SQLite default metadata so it is clearly SQLite-specific, and document that plugins submit only string, number, boolean or null values. Plugins that need structured data should serialize it themselves instead of relying on Datasette to special-case JSON.

Move the built-in json column type behavior onto the same plugin API used by external plugins: validate the textarea with field.setValidity() as the value changes, but submit plain text. Harden row edit value comparison so fixing invalid JSON in an existing row is not blocked by the original invalid value.

Update the JavaScript plugin documentation and Node-based tests for the revised field contract.
2026-06-14 13:58:55 -07:00
Simon Willison
b2de8b5d2e First draft of makeColumnField() plugin hook 2026-06-14 11:57:13 -07:00
Simon Willison
8568320a23 Replace jump_start() hook with JavaScript makeJumpSections() hook 2026-05-22 21:13:49 -07:00
Simon Willison
503545b203 JavaScript plugins documentation, closes #2250 2024-02-05 11:47:17 -08:00