@muibook/components 19.5.1 → 19.6.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.
@@ -1,7 +1,15 @@
1
1
  const e = {
2
2
  // FEEDBACK
3
3
  alert: ["alert", "success", "info", "warning", "error", "message", "banner", "notification"],
4
- message: ["message", "notice", "notification", "alert", "info", "positive", "neutral", "warning", "attention"],
4
+ message: [
5
+ "page message",
6
+ "page notice",
7
+ "persistent notice",
8
+ "persistent message",
9
+ "system notice",
10
+ "status notice",
11
+ "message banner"
12
+ ],
5
13
  loader: ["loader", "loading", "skeleton", "placeholder", "shimmer", "pulse", "fade", "spinner"],
6
14
  spinner: ["spinner", "loading", "busy", "indicator", "progress"],
7
15
  progress: ["progress", "bar", "loading", "completion", "percent", "syncing", "pending"],
@@ -24,6 +24,7 @@ CRITICAL RULES:
24
24
  11. Put visual backgrounds on layout style or SmartCard bg props.
25
25
  12. SmartCard props use kebab-case: bg-image, bg-color, logo-height.
26
26
  13. Normalize scanned Muibook/Figma names to Redactd component types before output.
27
+ 14. Do not use Message as a styled paragraph, inline note, or form helper. Message is only for persistent page-level notices with a heading and slotted body content.
27
28
 
28
29
  MUI SCAN NORMALIZATION RULES:
29
30
  - Normalize muiscan to Redactd types before output
@@ -60,7 +61,7 @@ TEXT NODE RULES FOR MUISCAN:
60
61
  - mui-badge: consume TEXT as the badge's direct rendered text; preserve before/after slot children; do not invent Body
61
62
  - mui-chip: consume TEXT as the chip's direct rendered text; preserve before/after slot children; do not invent Body
62
63
  - mui-alert: preserve variant/label, convert default content to Span, consume TEXT into Span.props.text, keep inline children such as Link, do not invent Body
63
- - mui-message: map scanned heading directly to Message.props.heading, preserve variant/icon/size, keep remaining children as default message content
64
+ - mui-message: map scanned heading directly to Message.props.heading, preserve variant/icon/size, keep remaining children as default message content; if there is no supporting body content, prefer Body or FormMessage instead of Message
64
65
  - Do not invent wrappers when the target already supports text
65
66
 
66
67
  Available Components:
@@ -71,7 +72,7 @@ LAYOUT:
71
72
  - Grid: col, space, padding, alignX, alignY, height, width, fill, viewport, style
72
73
  - Container: size (small|medium|large), center, style
73
74
  - Responsive: breakpoint, breakpoint-low, breakpoint-high; slots showBelow/showMiddle/showAbove
74
- - Rule: length, weight, direction (horizontal|vertical)
75
+ - Rule: length, weight (thin|thick|CSS size), direction (horizontal|vertical)
75
76
 
76
77
  SURFACES:
77
78
  - Card: use CardBody for card content
@@ -86,7 +87,7 @@ SURFACES:
86
87
 
87
88
  CONTENT:
88
89
  - Heading: text, size (1|2|3|4|5|6), level (1|2|3|4|5|6)
89
- - Body: text, size (x-small|small|medium|large), weight (regular|bold), variant (default|optional|success|warning|error), style
90
+ - Body: text, size (x-small|small|medium|large), weight (regular|bold), variant (default|optional|success|warning|error), style; use _Icon icon=mui-icon-info slot=before for lightweight inline guidance
90
91
  - Span: text, style; supports inline children such as Link
91
92
  - Code: size, scrollable
92
93
  - Quote: default text
@@ -139,7 +140,7 @@ NAVIGATION:
139
140
  - CarouselPanel: item, style
140
141
 
141
142
  FEEDBACK:
142
- - Message: heading, variant (plain|neutral|positive|info|warning|attention), icon, size (small|medium|large); slot default
143
+ - Message: heading, variant (neutral|positive|info|warning|attention), icon, size (small|medium|large); slot default. Use only for persistent page-level or section-level notices. Always provide a concise heading plus default slot body content, usually Body/List/Link. Do not use for inline guidance, styled text blocks, or form helper text.
143
144
  - Alert: variant (success|info|warning|error), label; slots default/action
144
145
  - Loader: loading, animation (pulsate|fade-in|translate), direction (up|right|down|left), duration; slot default
145
146
  - Spinner: size (xx-small|x-small|small|medium|large), color, duration, label, style
@@ -1,7 +1,7 @@
1
1
  import { getPartMap as r } from "../../utils/part-map/index.js";
2
2
  class l extends HTMLElement {
3
3
  static get observedAttributes() {
4
- return ["size", "weight", "variant"];
4
+ return ["size", "weight", "variant", "truncate", "clamp"];
5
5
  }
6
6
  constructor() {
7
7
  super(), this.attachShadow({ mode: "open" });
@@ -9,25 +9,36 @@ class l extends HTMLElement {
9
9
  async connectedCallback() {
10
10
  this.hasAttribute("size") || this.setAttribute("size", "medium"), this.hasAttribute("weight") || this.setAttribute("weight", "regular"), this.hasAttribute("variant") || this.setAttribute("variant", "default"), await this.waitForPartMap(), this.render();
11
11
  }
12
- attributeChangedCallback(t, e, s) {
13
- e !== s && this.shadowRoot && this.render();
12
+ attributeChangedCallback(t, e, i) {
13
+ e !== i && this.shadowRoot && this.render();
14
14
  }
15
15
  render() {
16
16
  if (!this.shadowRoot) return;
17
- const t = r("text", "spacing", "layout", "visual");
17
+ const t = r("text", "spacing", "layout", "visual"), e = this.getLineClamp();
18
18
  this.shadowRoot.innerHTML = /*html*/
19
19
  `
20
20
  <style>
21
- :host { display: block; }
21
+ :host {
22
+ display: block;
23
+ --body-line-clamp: ${e};
24
+ }
22
25
  :host([has-before]),
23
26
  :host([has-after]) {
24
27
  display: inline-flex;
25
28
  }
26
29
 
30
+ :host([truncate]) {
31
+ display: block;
32
+ min-width: 0;
33
+ max-width: 100%;
34
+ width: 100%;
35
+ }
36
+
27
37
  :host p {
28
38
  color: var(--text-color);
29
39
  margin: var(--space-000);
30
40
  display: block;
41
+ min-width: 0;
31
42
  width: 100%;
32
43
  }
33
44
 
@@ -41,9 +52,31 @@ class l extends HTMLElement {
41
52
  }
42
53
 
43
54
  .content {
55
+ max-width: 100%;
44
56
  min-width: 0;
45
57
  }
46
58
 
59
+ :host([truncate]) p,
60
+ :host([clamp]) p {
61
+ max-width: 100%;
62
+ }
63
+
64
+ :host([truncate]) .content {
65
+ display: block;
66
+ max-width: 100%;
67
+ width: 100%;
68
+ overflow: hidden;
69
+ text-overflow: ellipsis;
70
+ white-space: nowrap;
71
+ }
72
+
73
+ :host([clamp]:not([truncate])) .content {
74
+ display: -webkit-box;
75
+ overflow: hidden;
76
+ -webkit-box-orient: vertical;
77
+ -webkit-line-clamp: var(--body-line-clamp);
78
+ }
79
+
47
80
  ::slotted([slot="before"]),
48
81
  ::slotted([slot="after"]) {
49
82
  flex-shrink: 0;
@@ -64,7 +97,7 @@ class l extends HTMLElement {
64
97
 
65
98
  :host([size="large"]) ::slotted([slot="before"]),
66
99
  :host([size="large"]) ::slotted([slot="after"]) {
67
- margin-top: var(--body-inline-icon-offset-large, var(--body-inline-icon-offset, var(--stroke-size-050)));
100
+ margin-top: var(--body-inline-icon-offset-large, var(--body-inline-icon-offset, var(--stroke-size-300)));
68
101
  }
69
102
 
70
103
  :host([size="x-small"]) p {
@@ -100,6 +133,9 @@ class l extends HTMLElement {
100
133
  color: var(--text-color-optional);
101
134
  }
102
135
 
136
+ :host([variant="info"]) p {
137
+ color: var(--text-color-info);
138
+ }
103
139
  :host([variant="success"]) p {
104
140
  color: var(--text-color-success);
105
141
  }
@@ -116,6 +152,9 @@ class l extends HTMLElement {
116
152
  :host([variant="optional"]) ::slotted(.mui-icon) {
117
153
  fill: var(--text-color-optional);
118
154
  }
155
+ :host([variant="info"]) ::slotted(.mui-icon) {
156
+ fill: var(--text-color-info);
157
+ }
119
158
  :host([variant="success"]) ::slotted(.mui-icon) {
120
159
  fill: var(--text-color-success);
121
160
  }
@@ -135,28 +174,32 @@ class l extends HTMLElement {
135
174
  </p>
136
175
  `, this.setupSlotBehavior();
137
176
  }
177
+ getLineClamp() {
178
+ const t = Number(this.getAttribute("clamp"));
179
+ return Number.isFinite(t) && t > 0 ? Math.floor(t) : 2;
180
+ }
138
181
  setupSlotBehavior() {
139
182
  if (!this.shadowRoot) return;
140
- const t = this.shadowRoot.querySelector('slot[name="before"]'), e = this.shadowRoot.querySelector('slot[name="after"]'), s = () => {
141
- const a = (t == null ? void 0 : t.assignedElements({ flatten: !0 })) ?? [], i = (e == null ? void 0 : e.assignedElements({ flatten: !0 })) ?? [];
142
- a.length > 0 ? this.setAttribute("has-before", "") : this.removeAttribute("has-before"), i.length > 0 ? this.setAttribute("has-after", "") : this.removeAttribute("has-after"), this.syncInlineSlotSizes([...a, ...i]);
183
+ const t = this.shadowRoot.querySelector('slot[name="before"]'), e = this.shadowRoot.querySelector('slot[name="after"]'), i = () => {
184
+ const a = (t == null ? void 0 : t.assignedElements({ flatten: !0 })) ?? [], o = (e == null ? void 0 : e.assignedElements({ flatten: !0 })) ?? [];
185
+ a.length > 0 ? this.setAttribute("has-before", "") : this.removeAttribute("has-before"), o.length > 0 ? this.setAttribute("has-after", "") : this.removeAttribute("has-after"), this.syncInlineSlotSizes([...a, ...o]);
143
186
  };
144
- t == null || t.addEventListener("slotchange", s), e == null || e.addEventListener("slotchange", s), s();
187
+ t == null || t.addEventListener("slotchange", i), e == null || e.addEventListener("slotchange", i), i();
145
188
  }
146
189
  syncInlineSlotSizes(t) {
147
- const s = {
190
+ const i = {
148
191
  "x-small": "x-small",
149
192
  small: "small",
150
193
  medium: "small",
151
194
  large: "medium"
152
- }[this.getAttribute("size") || "medium"] || "small", i = {
195
+ }[this.getAttribute("size") || "medium"] || "small", o = {
153
196
  "x-small": "xx-small",
154
197
  small: "x-small",
155
198
  medium: "small",
156
199
  large: "medium"
157
200
  }[this.getAttribute("size") || "medium"] || "small";
158
- t.forEach((o) => {
159
- o.tagName.startsWith("MUI-ICON-") && o.setAttribute("size", s), o.tagName === "MUI-BADGE" && o.setAttribute("size", i);
201
+ t.forEach((s) => {
202
+ s.tagName.startsWith("MUI-ICON-") && s.setAttribute("size", i), s.tagName === "MUI-BADGE" && s.setAttribute("size", o);
160
203
  });
161
204
  }
162
205
  waitForPartMap() {
@@ -10,6 +10,7 @@ class a extends HTMLElement {
10
10
  getIconColor(t) {
11
11
  return {
12
12
  optional: "var(--text-color-optional)",
13
+ info: "var(--text-color-info)",
13
14
  warning: "var(--text-color-warning)",
14
15
  success: "var(--text-color-success)",
15
16
  error: "var(--text-color-error)"
@@ -25,9 +26,9 @@ class a extends HTMLElement {
25
26
  }
26
27
  syncBeforeIcon() {
27
28
  if (!this.shadowRoot) return;
28
- const t = this.shadowRoot.querySelector('slot[name="before"]'), e = this.getIconColor(this.getAttribute("variant") || "optional"), o = this.getIconSize(this.getAttribute("size") || "small");
29
- ((t == null ? void 0 : t.assignedElements({ flatten: !0 })) ?? []).forEach((s) => {
30
- s.tagName.toLowerCase().startsWith("mui-icon-") && (s.hasAttribute("color") || s.setAttribute("color", e), s.hasAttribute("size") || s.setAttribute("size", o));
29
+ const t = this.shadowRoot.querySelector('slot[name="before"]'), s = this.getIconColor(this.getAttribute("variant") || "optional"), o = this.getIconSize(this.getAttribute("size") || "small");
30
+ ((t == null ? void 0 : t.assignedElements({ flatten: !0 })) ?? []).forEach((e) => {
31
+ e.tagName.toLowerCase().startsWith("mui-icon-") && (e.hasAttribute("color") || e.setAttribute("color", s), e.hasAttribute("size") || e.setAttribute("size", o));
31
32
  });
32
33
  }
33
34
  connectedCallback() {
@@ -38,7 +39,7 @@ class a extends HTMLElement {
38
39
  }
39
40
  render() {
40
41
  if (!this.shadowRoot) return;
41
- const t = this.getAttribute("size") || "small", e = this.getAttribute("weight") || "regular", o = this.getAttribute("variant") || "optional";
42
+ const t = this.getAttribute("size") || "small", s = this.getAttribute("weight") || "regular", o = this.getAttribute("variant") || "optional", r = this.querySelector('[slot="after"]') !== null;
42
43
  this.shadowRoot.innerHTML = /*html*/
43
44
  `
44
45
  <style>
@@ -50,23 +51,30 @@ class a extends HTMLElement {
50
51
  margin-inline-start: var(--stroke-size-100);
51
52
  margin-block-start: var(--space-200);
52
53
  }
54
+ .slot-wrapper {
55
+ display: inline-flex;
56
+ }
53
57
  </style>
54
58
 
55
- <mui-body size="${t}" weight="${e}" variant="${o}">
56
- <slot slot="before" name="before">
57
- <mui-icon-info id="default-before-icon" size="${this.getIconSize(t)}" color="${this.getIconColor(o)}"></mui-icon-info>
58
- </slot>
59
+ <mui-body size="${t}" weight="${s}" variant="${o}">
60
+ <span slot="before" class="slot-wrapper">
61
+ <slot name="before">
62
+ <mui-icon-info id="default-before-icon" size="${this.getIconSize(t)}" color="${this.getIconColor(o)}"></mui-icon-info>
63
+ </slot>
64
+ </span>
59
65
  <slot></slot>
60
- <slot slot="after" name="after"></slot>
66
+ ${r ? `<span slot="after" class="slot-wrapper">
67
+ <slot name="after"></slot>
68
+ </span>` : ""}
61
69
  </mui-body>
62
70
  `;
63
- const i = this.shadowRoot.querySelector('slot[name="before"]');
64
- i == null || i.addEventListener("slotchange", () => this.syncBeforeIcon()), this.syncBeforeIcon();
71
+ const e = this.shadowRoot.querySelector('slot[name="before"]');
72
+ e == null || e.addEventListener("slotchange", () => this.syncBeforeIcon()), this.syncBeforeIcon();
65
73
  }
66
74
  }
67
75
  customElements.get("mui-form-message") || customElements.define("mui-form-message", a);
68
76
  if (!customElements.get("mui-form-hint")) {
69
- class r extends a {
77
+ class i extends a {
70
78
  }
71
- customElements.define("mui-form-hint", r);
79
+ customElements.define("mui-form-hint", i);
72
80
  }
@@ -1,6 +1,6 @@
1
- class n extends HTMLElement {
1
+ class h extends HTMLElement {
2
2
  static get observedAttributes() {
3
- return ["size", "level"];
3
+ return ["size", "level", "truncate", "clamp"];
4
4
  }
5
5
  constructor() {
6
6
  super(), this.attachShadow({ mode: "open" });
@@ -8,21 +8,53 @@ class n extends HTMLElement {
8
8
  connectedCallback() {
9
9
  this.render();
10
10
  }
11
- attributeChangedCallback(i, t, e) {
12
- t !== e && this.shadowRoot && this.render();
11
+ attributeChangedCallback(e, i, t) {
12
+ i !== t && this.shadowRoot && this.render();
13
13
  }
14
14
  render() {
15
15
  if (!this.shadowRoot) return;
16
- const i = this.getAttribute("size") || "1", e = `h${this.getAttribute("level") || i}`;
16
+ const e = this.getAttribute("size") || "1", t = `h${this.getAttribute("level") || e}`, n = this.getLineClamp();
17
17
  this.shadowRoot.innerHTML = /*html*/
18
18
  `
19
19
  <style>
20
- :host { display: block; }
20
+ :host {
21
+ display: block;
22
+ --heading-line-clamp: ${n};
23
+ }
24
+
25
+ :host([truncate]) {
26
+ min-width: 0;
27
+ max-width: 100%;
28
+ width: 100%;
29
+ }
21
30
 
22
31
  h1, h2, h3, h4, h5, h6 {
23
32
  margin: var(--space-000);
24
33
  font-weight: var(--heading-font-weight);
25
34
  color: var(--heading-text-color);
35
+ min-width: 0;
36
+ width: 100%;
37
+ }
38
+
39
+ .content {
40
+ max-width: 100%;
41
+ min-width: 0;
42
+ }
43
+
44
+ :host([truncate]) .content {
45
+ display: block;
46
+ max-width: 100%;
47
+ width: 100%;
48
+ overflow: hidden;
49
+ text-overflow: ellipsis;
50
+ white-space: nowrap;
51
+ }
52
+
53
+ :host([clamp]:not([truncate])) .content {
54
+ display: -webkit-box;
55
+ overflow: hidden;
56
+ -webkit-box-orient: vertical;
57
+ -webkit-line-clamp: var(--heading-line-clamp);
26
58
  }
27
59
 
28
60
  .size-1 { font-size: var(--heading-font-size-100); line-height: var(--heading-line-height-100); }
@@ -32,10 +64,14 @@ class n extends HTMLElement {
32
64
  .size-5 { font-size: var(--heading-font-size-500); line-height: var(--heading-line-height-500); }
33
65
  .size-6 { font-size: var(--heading-font-size-600); line-height: var(--heading-line-height-600); }
34
66
  </style>
35
- <${e} class="size-${i}">
36
- <slot></slot>
37
- </${e}>
67
+ <${t} class="size-${e}">
68
+ <span class="content"><slot></slot></span>
69
+ </${t}>
38
70
  `;
39
71
  }
72
+ getLineClamp() {
73
+ const e = Number(this.getAttribute("clamp"));
74
+ return Number.isFinite(e) && e > 0 ? Math.floor(e) : 2;
75
+ }
40
76
  }
41
- customElements.get("mui-heading") || customElements.define("mui-heading", n);
77
+ customElements.get("mui-heading") || customElements.define("mui-heading", h);
@@ -133,11 +133,11 @@ class T extends HTMLElement {
133
133
  }
134
134
  getDelay() {
135
135
  const t = Number(this.getAttribute("delay"));
136
- return Number.isFinite(t) ? Math.min(2e3, Math.max(1e3, t)) : 1500;
136
+ return Number.isFinite(t) ? Math.min(2e3, Math.max(250, t)) : 500;
137
137
  }
138
138
  getInitialDelay() {
139
139
  const t = Number(this.getAttribute("initial-delay"));
140
- return Number.isFinite(t) ? Math.min(2e3, Math.max(1e3, t)) : 1500;
140
+ return Number.isFinite(t) ? Math.min(2e3, Math.max(250, t)) : 500;
141
141
  }
142
142
  openWithDelay() {
143
143
  this.closeTimer && (window.clearTimeout(this.closeTimer), this.closeTimer = null);
@@ -15,8 +15,15 @@ class s extends HTMLElement {
15
15
  const t = !!this.closest("mui-card"), e = !!this.closest("mui-form-section"), i = !!this.closest("mui-dialog"), o = !!this.closest("mui-drawer");
16
16
  this.toggleAttribute("in-card", t), this.toggleAttribute("in-form-section", e), this.toggleAttribute("in-dialog", i), this.toggleAttribute("in-drawer", o);
17
17
  }
18
+ getRuleWeight() {
19
+ const t = this.getAttribute("weight") || "var(--stroke-size-100)";
20
+ return {
21
+ thin: "var(--stroke-size-100)",
22
+ thick: "var(--stroke-size-200)"
23
+ }[t] || t;
24
+ }
18
25
  updateStyles() {
19
- const t = this.getAttribute("length") || "100%", e = this.getAttribute("weight") || "1px", i = (
26
+ const t = this.getAttribute("length") || "100%", e = this.getRuleWeight(), i = (
20
27
  /*css*/
21
28
  `
22
29
  :host {
@@ -39,7 +39,7 @@ class i extends HTMLElement {
39
39
  return this.querySelector('[slot="accessory"]') !== null;
40
40
  }
41
41
  render() {
42
- const a = this.variant === "action", t = this.getAttribute("col") || "1fr 1fr", r = this.getAttribute("space") || "var(--space-500)", e = this.hasAccessorySlot(), s = (
42
+ const a = this.variant === "action", t = this.getAttribute("col") || (a ? "minmax(0, 1fr) auto" : "1fr 1fr"), r = this.getAttribute("space") || "var(--space-500)", e = this.hasAccessorySlot(), s = (
43
43
  /*css*/
44
44
  `
45
45
  :host {
@@ -72,6 +72,14 @@ class i extends HTMLElement {
72
72
  text-align: left;
73
73
  }
74
74
 
75
+ .action::part(grid-template-columns) {
76
+ grid-template-columns: ${t};
77
+ }
78
+
79
+ .action::part(gap) {
80
+ gap: ${r};
81
+ }
82
+
75
83
  .action:focus {
76
84
  z-index: 1;
77
85
  }
@@ -1,6 +1,6 @@
1
1
 
2
2
  /* ================================================================================================== */
3
- /* Don't edit directly • Generated on Tue, 26 May 2026 10:59:50 GMT • muibook.com */
3
+ /* Don't edit directly • Generated on Thu, 28 May 2026 12:53:59 GMT • muibook.com */
4
4
  /* ================================================================================================== */
5
5
 
6
6
  /* ================================================================================================== */
@@ -28,6 +28,7 @@
28
28
  /* ======================================= 21 / 14 = 1.500 ======================================= */
29
29
  /* ======================================= 24 / 16 = 1.500 ======================================= */
30
30
  /* ======================================= 24 / 18 = 1.333 ======================================= */
31
+ /* ======================================= 30 / 18 = 1.667 ======================================= */
31
32
  /* ======================================= 24 / 21 = 1.143 ======================================= */
32
33
  /* ======================================= 36 / 24 = 1.500 ======================================= */
33
34
  /* ======================================= 48 / 36 = 1.333 ======================================= */
@@ -62,6 +63,7 @@
62
63
  --line-height-50: 1.5;
63
64
  --line-height-100: 1.5;
64
65
  --line-height-200: 1.33333333;
66
+ --line-height-225: 1.66666667;
65
67
  --line-height-300: 1.14285714;
66
68
  --line-height-400: 1.5;
67
69
  --line-height-500: 1.33333333;
@@ -241,6 +241,7 @@ html[data-theme="light"] {
241
241
  --border-color: var(--black-opacity-20);
242
242
  /* Text */
243
243
  --text-color: var(--grey-900);
244
+ --text-color-info: var(--blue-600);
244
245
  --text-color-success: var(--green-600);
245
246
  --text-color-warning: var(--orange-600);
246
247
  --text-color-error: var(--red-600);
@@ -597,6 +598,7 @@ html[data-theme="dark"] {
597
598
  --border-color: var(--white-opacity-20);
598
599
  /* Text */
599
600
  --text-color: var(--grey-200);
601
+ --text-color-info: var(--blue-400);
600
602
  --text-color-success: var(--green-400);
601
603
  --text-color-warning: var(--orange-400);
602
604
  --text-color-error: var(--red-400);
@@ -839,7 +841,7 @@ html[data-theme="dark"] {
839
841
  --text-line-height-xs: var(--line-height-25);
840
842
  --text-line-height-s: var(--line-height-50);
841
843
  --text-line-height-m: var(--line-height-100);
842
- --text-line-height-l: var(--line-height-200);
844
+ --text-line-height-l: var(--line-height-225);
843
845
  --text-font-size-xs: var(--font-size-25);
844
846
  --text-font-size-s: var(--font-size-50);
845
847
  --text-font-size-m: var(--font-size-100);