@mlola-ui/behavior 1.0.5 → 1.0.7

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/README.md CHANGED
@@ -33,6 +33,12 @@ npm install @mlola-ui/behavior
33
33
  It is idempotent, so it is safe to call after a framework re-render, a turbo
34
34
  navigation, or an htmx swap.
35
35
 
36
+ ## Examples
37
+
38
+ `examples/` holds the markup for each behavior, one file per behavior, as
39
+ it should be written by hand. They are the markup the browser suite runs in
40
+ Chromium, Firefox and WebKit, and the markup the component docs show.
41
+
36
42
  ## Implemented behaviors
37
43
 
38
44
  `accordion`, `tabs`, `dropdown-menu`, `select`, `modal`, `sheet`, `tooltip`,
@@ -0,0 +1,24 @@
1
+ <div class="ml-accordion" data-ml="accordion">
2
+ <article class="ml-accordion-item" data-state="open">
3
+ <h3 class="ml-accordion-heading">
4
+ <button id="t1" class="ml-accordion-trigger" data-state="open" aria-expanded="true" aria-controls="p1">
5
+ <span>Is there a free plan?</span>
6
+ <svg class="mlola-glyph" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m6 9 6 6 6-6"/></svg>
7
+ </button>
8
+ </h3>
9
+ <div id="p1" class="ml-accordion-panel" role="region" aria-labelledby="t1" data-state="open">
10
+ <p>Yes. The components in the open-source registry are free forever.</p>
11
+ </div>
12
+ </article>
13
+ <article class="ml-accordion-item" data-state="closed">
14
+ <h3 class="ml-accordion-heading">
15
+ <button id="t2" class="ml-accordion-trigger" data-state="closed" aria-expanded="false" aria-controls="p2">
16
+ <span>Can I change themes later?</span>
17
+ <svg class="mlola-glyph" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m6 9 6 6 6-6"/></svg>
18
+ </button>
19
+ </h3>
20
+ <div id="p2" class="ml-accordion-panel" role="region" aria-labelledby="t2" data-state="closed" hidden>
21
+ <p>Change data-theme on any ancestor. Nothing else moves.</p>
22
+ </div>
23
+ </article>
24
+ </div>
@@ -0,0 +1,11 @@
1
+ <div class="ml-dropdown" data-ml="dropdown-menu">
2
+ <button class="ml-dropdown-trigger" type="button" aria-haspopup="menu" aria-expanded="false">
3
+ <span class="ml-dropdown-trigger-label">File</span>
4
+ <svg class="mlola-glyph" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m6 9 6 6 6-6"/></svg>
5
+ </button>
6
+ <div class="ml-dropdown-menu" role="menu" aria-label="File" data-align="start" hidden>
7
+ <button class="ml-dropdown-item" type="button" role="menuitem">New</button>
8
+ <button class="ml-dropdown-item" type="button" role="menuitem">Open</button>
9
+ <button class="ml-dropdown-item" type="button" role="menuitem" data-danger>Delete</button>
10
+ </div>
11
+ </div>
@@ -0,0 +1,16 @@
1
+ <button class="ml-button" type="button" data-variant="danger" data-ml-opens="delete-project">
2
+ <span class="ml-button-label">Delete project</span>
3
+ </button>
4
+
5
+ <div class="ml-modal-overlay" data-ml-for="delete-project" hidden></div>
6
+ <div class="ml-modal" id="delete-project" data-ml="modal" role="alertdialog" aria-modal="true" aria-labelledby="delete-project-title" data-size="sm" tabindex="-1" hidden>
7
+ <div class="ml-modal-header">
8
+ <h2 class="ml-modal-title" id="delete-project-title">Delete project</h2>
9
+ <button class="ml-modal-close" type="button" aria-label="Close dialog"><svg class="mlola-glyph" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
10
+ </div>
11
+ <div class="ml-modal-body">This removes the project and every deployment attached to it.</div>
12
+ <div class="ml-modal-footer">
13
+ <button class="ml-button" type="button" data-variant="secondary" data-ml-close><span class="ml-button-label">Keep it</span></button>
14
+ <button class="ml-button" type="button" data-variant="danger"><span class="ml-button-label">Delete</span></button>
15
+ </div>
16
+ </div>
@@ -0,0 +1,16 @@
1
+ <div class="ml-select-root" data-ml="select">
2
+ <span class="ml-select-label" id="fruit-label">Fruit</span>
3
+ <div class="ml-select-control">
4
+ <button class="ml-select" type="button" role="combobox" aria-expanded="false" aria-controls="fruit-list" aria-labelledby="fruit-label" data-state="closed">
5
+ <span class="ml-select-value" data-placeholder>Select…</span>
6
+ <span class="ml-select-chevron" aria-hidden="true"><svg class="mlola-glyph" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m6 9 6 6 6-6"/></svg></span>
7
+ </button>
8
+ </div>
9
+ <div class="ml-select-popover" hidden>
10
+ <ul class="ml-select-list" id="fruit-list" role="listbox" aria-labelledby="fruit-label">
11
+ <li class="ml-select-option" id="opt-apple" role="option" aria-selected="false" data-state="unchecked">Apple</li>
12
+ <li class="ml-select-option" id="opt-pear" role="option" aria-selected="false" data-state="unchecked">Pear</li>
13
+ <li class="ml-select-option" id="opt-durian" role="option" aria-selected="false" aria-disabled="true" data-state="unchecked">Durian</li>
14
+ </ul>
15
+ </div>
16
+ </div>
@@ -0,0 +1,17 @@
1
+ <button class="ml-button" type="button" data-variant="secondary" data-ml-opens="account-settings">
2
+ <span class="ml-button-label">Settings</span>
3
+ </button>
4
+
5
+ <div class="ml-sheet-overlay" data-ml-for="account-settings" hidden></div>
6
+ <div class="ml-sheet-panel" id="account-settings" data-ml="sheet" role="dialog" aria-modal="true" aria-labelledby="account-settings-title" data-side="right" data-size="md" tabindex="-1" hidden>
7
+ <div class="ml-sheet-header">
8
+ <div class="ml-sheet-heading">
9
+ <h2 class="ml-sheet-title" id="account-settings-title">Account settings</h2>
10
+ <p class="ml-sheet-description">Changes apply instantly.</p>
11
+ </div>
12
+ <button class="ml-sheet-close" type="button" aria-label="Close panel"><svg class="mlola-glyph" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
13
+ </div>
14
+ <div class="ml-sheet-body">
15
+ <p>Escape closes the panel, and so does the backdrop.</p>
16
+ </div>
17
+ </div>
@@ -0,0 +1,14 @@
1
+ <div class="ml-slider-field" data-ml="slider" data-size="md" data-ml-step="5">
2
+ <div class="ml-slider-header">
3
+ <span class="ml-slider-label" id="bright-label">Brightness</span>
4
+ <span class="ml-slider-output">40</span>
5
+ </div>
6
+ <div class="ml-slider">
7
+ <div class="ml-slider-track">
8
+ <span class="ml-slider-range" style="width: 40%"></span>
9
+ <span class="ml-slider-thumb" id="bright-thumb" role="slider" tabindex="0"
10
+ aria-labelledby="bright-label" aria-valuemin="0" aria-valuemax="100" aria-valuenow="40"
11
+ style="left: 40%"></span>
12
+ </div>
13
+ </div>
14
+ </div>
@@ -0,0 +1,6 @@
1
+ <span class="ml-switch-field">
2
+ <button class="ml-toggle" type="button" data-ml="switch" role="switch" aria-checked="false" aria-labelledby="notify-label" data-state="unchecked" data-size="md" data-hit="expand">
3
+ <span class="ml-toggle-thumb" aria-hidden="true"></span>
4
+ </button>
5
+ <span class="ml-switch-label" id="notify-label">Email notifications</span>
6
+ </span>
@@ -0,0 +1,10 @@
1
+ <div class="ml-tabs" data-ml="tabs" data-variant="default" data-orientation="horizontal">
2
+ <div class="ml-tabs-list" role="tablist" aria-label="Project" aria-orientation="horizontal">
3
+ <button class="ml-tabs-trigger" type="button" role="tab" id="tab-a" aria-controls="panel-a" aria-selected="true" data-state="active" tabindex="0">Overview</button>
4
+ <button class="ml-tabs-trigger" type="button" role="tab" id="tab-b" aria-controls="panel-b" aria-selected="false" data-state="inactive" tabindex="-1">Activity</button>
5
+ <button class="ml-tabs-trigger" type="button" role="tab" id="tab-c" aria-controls="panel-c" aria-selected="false" data-state="inactive" tabindex="-1">Settings</button>
6
+ </div>
7
+ <div class="ml-tabs-content" role="tabpanel" id="panel-a" aria-labelledby="tab-a" tabindex="0" data-state="active">Overview panel</div>
8
+ <div class="ml-tabs-content" role="tabpanel" id="panel-b" aria-labelledby="tab-b" tabindex="0" data-state="inactive" hidden>Activity panel</div>
9
+ <div class="ml-tabs-content" role="tabpanel" id="panel-c" aria-labelledby="tab-c" tabindex="0" data-state="inactive" hidden>Settings panel</div>
10
+ </div>
@@ -0,0 +1,8 @@
1
+ <div class="ml-toaster" data-ml="toast" role="region" aria-label="Notifications" data-position="top-right">
2
+ <div class="ml-toast" role="status" aria-live="polite" aria-atomic="true" data-tone="success" data-ml-duration="6000">
3
+ <div class="ml-toast-content">
4
+ <p class="ml-toast-message">Draft saved to your workspace.</p>
5
+ </div>
6
+ <button class="ml-toast-close" type="button" aria-label="Dismiss notification"><svg class="mlola-glyph" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
7
+ </div>
8
+ </div>
@@ -0,0 +1,7 @@
1
+ <span class="ml-tooltip-root" data-ml="tooltip">
2
+ <button class="ml-button" type="button" data-variant="secondary" data-size="sm"><span class="ml-button-label">Share</span></button>
3
+ <span class="ml-tooltip" id="share-tip" role="tooltip" data-side="top" hidden>
4
+ Copy a link to this page
5
+ <span class="ml-tooltip-arrow" aria-hidden="true"></span>
6
+ </span>
7
+ </span>
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@mlola-ui/behavior",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Framework-free behavior for Mlola UI markup: standard DOM, no runtime peers",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "sideEffects": false,
8
8
  "files": [
9
- "src"
9
+ "src",
10
+ "examples"
10
11
  ],
11
12
  "exports": {
12
13
  ".": "./src/index.js",
package/src/index.js CHANGED
@@ -265,7 +265,9 @@ const behaviors = {
265
265
  open(opener_);
266
266
  return;
267
267
  }
268
- if (root.querySelector(".ml-modal-close, .ml-sheet-close")?.contains(event.target)) close();
268
+ // The corner button, or any control marked data-ml-close, such as Cancel.
269
+ const closer = event.target.closest(".ml-modal-close, .ml-sheet-close, [data-ml-close]");
270
+ if (closer && root.contains(closer)) close();
269
271
  if (closeOnOverlay && event.target === overlay()) close();
270
272
  }),
271
273
  on(document, "keydown", (event) => {