@mason-ds/vue 0.2.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,1317 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Badge: () => Badge,
24
+ Button: () => Button,
25
+ Callout: () => Callout,
26
+ Card: () => Card,
27
+ Checkbox: () => Checkbox,
28
+ Divider: () => Divider,
29
+ Link: () => Link,
30
+ MasonProvider: () => MasonProvider,
31
+ Select: () => Select,
32
+ Spinner: () => Spinner,
33
+ Stack: () => Stack,
34
+ Text: () => Text,
35
+ TextField: () => TextField
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+
39
+ // src/provider.ts
40
+ var import_vue = require("vue");
41
+ var MasonProvider = (0, import_vue.defineComponent)({
42
+ name: "MasonProvider",
43
+ props: {
44
+ theme: {
45
+ type: String,
46
+ default: "light"
47
+ }
48
+ },
49
+ setup(props, { slots }) {
50
+ return () => (0, import_vue.h)(
51
+ "div",
52
+ {
53
+ "data-mason-provider": "",
54
+ "data-mason-theme": props.theme
55
+ },
56
+ slots.default?.()
57
+ );
58
+ }
59
+ });
60
+
61
+ // src/Text.ts
62
+ var import_vue2 = require("vue");
63
+
64
+ // src/styles.ts
65
+ var import_tokens = require("@mason-ds/tokens");
66
+ function cssVar(path) {
67
+ return `var(${(0, import_tokens.getSemanticCssVar)(path)})`;
68
+ }
69
+ function spacingVar(axis, level) {
70
+ return cssVar(`spacing.${axis}.${level}`);
71
+ }
72
+ function radiusVar(level) {
73
+ return cssVar(`radius.${level}`);
74
+ }
75
+ function shadowVar(level) {
76
+ return cssVar(`shadow.${level}`);
77
+ }
78
+ function textColorVar(tone) {
79
+ return cssVar(`color.text.${tone}`);
80
+ }
81
+ function typographyStyle(variant) {
82
+ return {
83
+ fontFamily: cssVar(`font.${variant}.family`),
84
+ fontSize: cssVar(`font.${variant}.size`),
85
+ fontWeight: cssVar(`font.${variant}.weight`),
86
+ lineHeight: cssVar(`font.${variant}.lineHeight`),
87
+ letterSpacing: cssVar(`font.${variant}.letterSpacing`)
88
+ };
89
+ }
90
+ function mergeClassName(...parts) {
91
+ const merged = parts.filter(Boolean).join(" ");
92
+ return merged.length > 0 ? merged : void 0;
93
+ }
94
+
95
+ // src/textStyles.ts
96
+ function textStyle({
97
+ variant = "body.md",
98
+ tone = "primary",
99
+ align,
100
+ truncate = false
101
+ }) {
102
+ return {
103
+ margin: "0",
104
+ color: textColorVar(tone),
105
+ ...typographyStyle(variant),
106
+ ...align ? { textAlign: align } : null,
107
+ ...truncate ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } : null
108
+ };
109
+ }
110
+
111
+ // src/Text.ts
112
+ var Text = (0, import_vue2.defineComponent)({
113
+ name: "MasonText",
114
+ inheritAttrs: false,
115
+ props: {
116
+ as: {
117
+ type: String,
118
+ default: "p"
119
+ },
120
+ variant: {
121
+ type: String,
122
+ default: "body.md"
123
+ },
124
+ tone: {
125
+ type: String,
126
+ default: "primary"
127
+ },
128
+ align: {
129
+ type: String,
130
+ default: void 0
131
+ },
132
+ truncate: {
133
+ type: Boolean,
134
+ default: false
135
+ }
136
+ },
137
+ setup(props, { slots, attrs }) {
138
+ return () => {
139
+ const { class: attrClass, style: attrStyle, ...rest } = attrs;
140
+ return (0, import_vue2.h)(
141
+ props.as,
142
+ {
143
+ ...rest,
144
+ "data-mason-component": "text",
145
+ "data-variant": props.variant,
146
+ class: mergeClassName(attrClass),
147
+ style: [
148
+ textStyle({
149
+ variant: props.variant,
150
+ tone: props.tone,
151
+ align: props.align,
152
+ truncate: props.truncate
153
+ }),
154
+ attrStyle
155
+ ]
156
+ },
157
+ slots.default?.()
158
+ );
159
+ };
160
+ }
161
+ });
162
+
163
+ // src/Stack.ts
164
+ var import_vue3 = require("vue");
165
+
166
+ // src/stackStyles.ts
167
+ var FLEX_ALIGN = {
168
+ start: "flex-start",
169
+ center: "center",
170
+ end: "flex-end",
171
+ stretch: "stretch",
172
+ baseline: "baseline"
173
+ };
174
+ var FLEX_JUSTIFY = {
175
+ start: "flex-start",
176
+ center: "center",
177
+ end: "flex-end",
178
+ between: "space-between"
179
+ };
180
+ function stackStyle({
181
+ direction = "column",
182
+ gap = "md",
183
+ align,
184
+ justify,
185
+ wrap = false,
186
+ inline = false
187
+ }) {
188
+ return {
189
+ display: inline ? "inline-flex" : "flex",
190
+ flexDirection: direction,
191
+ gap: spacingVar(direction === "row" ? "inline" : "stack", gap),
192
+ flexWrap: wrap ? "wrap" : "nowrap",
193
+ minWidth: "0",
194
+ ...align ? { alignItems: FLEX_ALIGN[align] } : null,
195
+ ...justify ? { justifyContent: FLEX_JUSTIFY[justify] } : null
196
+ };
197
+ }
198
+
199
+ // src/Stack.ts
200
+ var Stack = (0, import_vue3.defineComponent)({
201
+ name: "MasonStack",
202
+ inheritAttrs: false,
203
+ props: {
204
+ direction: {
205
+ type: String,
206
+ default: "column"
207
+ },
208
+ gap: {
209
+ type: String,
210
+ default: "md"
211
+ },
212
+ align: {
213
+ type: String,
214
+ default: void 0
215
+ },
216
+ justify: {
217
+ type: String,
218
+ default: void 0
219
+ },
220
+ wrap: {
221
+ type: Boolean,
222
+ default: false
223
+ },
224
+ inline: {
225
+ type: Boolean,
226
+ default: false
227
+ }
228
+ },
229
+ setup(props, { slots, attrs }) {
230
+ return () => {
231
+ const { class: attrClass, style: attrStyle, ...rest } = attrs;
232
+ return (0, import_vue3.h)(
233
+ "div",
234
+ {
235
+ ...rest,
236
+ "data-mason-component": "stack",
237
+ "data-direction": props.direction,
238
+ class: mergeClassName(attrClass),
239
+ style: [
240
+ stackStyle({
241
+ direction: props.direction,
242
+ gap: props.gap,
243
+ align: props.align,
244
+ justify: props.justify,
245
+ wrap: props.wrap,
246
+ inline: props.inline
247
+ }),
248
+ attrStyle
249
+ ]
250
+ },
251
+ slots.default?.()
252
+ );
253
+ };
254
+ }
255
+ });
256
+
257
+ // src/Card.ts
258
+ var import_vue4 = require("vue");
259
+
260
+ // src/cardStyles.ts
261
+ var TONE_BG = {
262
+ surface: "color.bg.surface",
263
+ canvas: "color.bg.canvas",
264
+ elevated: "color.bg.elevated"
265
+ };
266
+ function cardStyle({
267
+ padding = "md",
268
+ elevation = "sm",
269
+ radius = "md",
270
+ tone = "surface",
271
+ bordered = true
272
+ }) {
273
+ return {
274
+ display: "block",
275
+ padding: spacingVar("inset", padding),
276
+ backgroundColor: cssVar(TONE_BG[tone]),
277
+ color: cssVar("color.text.primary"),
278
+ border: bordered ? `1px solid ${cssVar("color.border.subtle")}` : "none",
279
+ borderRadius: radiusVar(radius),
280
+ boxShadow: shadowVar(elevation),
281
+ boxSizing: "border-box",
282
+ minWidth: "0"
283
+ };
284
+ }
285
+
286
+ // src/Card.ts
287
+ var Card = (0, import_vue4.defineComponent)({
288
+ name: "MasonCard",
289
+ inheritAttrs: false,
290
+ props: {
291
+ padding: {
292
+ type: String,
293
+ default: "md"
294
+ },
295
+ elevation: {
296
+ type: String,
297
+ default: "sm"
298
+ },
299
+ radius: {
300
+ type: String,
301
+ default: "md"
302
+ },
303
+ tone: {
304
+ type: String,
305
+ default: "surface"
306
+ },
307
+ bordered: {
308
+ type: Boolean,
309
+ default: true
310
+ }
311
+ },
312
+ setup(props, { slots, attrs }) {
313
+ return () => {
314
+ const { class: attrClass, style: attrStyle, ...rest } = attrs;
315
+ return (0, import_vue4.h)(
316
+ "div",
317
+ {
318
+ ...rest,
319
+ "data-mason-component": "card",
320
+ "data-tone": props.tone,
321
+ class: mergeClassName(attrClass),
322
+ style: [
323
+ cardStyle({
324
+ padding: props.padding,
325
+ elevation: props.elevation,
326
+ radius: props.radius,
327
+ tone: props.tone,
328
+ bordered: props.bordered
329
+ }),
330
+ attrStyle
331
+ ]
332
+ },
333
+ slots.default?.()
334
+ );
335
+ };
336
+ }
337
+ });
338
+
339
+ // src/Divider.ts
340
+ var import_vue5 = require("vue");
341
+
342
+ // src/dividerStyles.ts
343
+ function dividerStyle(orientation = "horizontal") {
344
+ const line = `1px solid ${cssVar("color.border.subtle")}`;
345
+ if (orientation === "vertical") {
346
+ return {
347
+ alignSelf: "stretch",
348
+ width: "0",
349
+ minHeight: "1em",
350
+ margin: "0",
351
+ border: "none",
352
+ borderInlineStart: line
353
+ };
354
+ }
355
+ return {
356
+ width: "100%",
357
+ height: "0",
358
+ margin: "0",
359
+ border: "none",
360
+ borderBlockStart: line
361
+ };
362
+ }
363
+
364
+ // src/Divider.ts
365
+ var Divider = (0, import_vue5.defineComponent)({
366
+ name: "MasonDivider",
367
+ inheritAttrs: false,
368
+ props: {
369
+ orientation: {
370
+ type: String,
371
+ default: "horizontal"
372
+ }
373
+ },
374
+ setup(props, { attrs }) {
375
+ return () => {
376
+ const { class: attrClass, style: attrStyle, ...rest } = attrs;
377
+ return (0, import_vue5.h)("hr", {
378
+ ...rest,
379
+ "data-mason-component": "divider",
380
+ "data-orientation": props.orientation,
381
+ "aria-orientation": props.orientation === "vertical" ? "vertical" : void 0,
382
+ class: mergeClassName(attrClass),
383
+ style: [dividerStyle(props.orientation), attrStyle]
384
+ });
385
+ };
386
+ }
387
+ });
388
+
389
+ // src/Link.ts
390
+ var import_vue6 = require("vue");
391
+
392
+ // src/linkStyles.ts
393
+ function linkStyle({
394
+ tone = "link",
395
+ underline = "hover"
396
+ }) {
397
+ return {
398
+ color: tone === "inherit" ? "inherit" : textColorVar("link"),
399
+ textDecoration: underline === "always" ? "underline" : "none",
400
+ textUnderlineOffset: "0.15em",
401
+ borderRadius: radiusVar("sm"),
402
+ cursor: "pointer"
403
+ };
404
+ }
405
+
406
+ // src/Link.ts
407
+ var Link = (0, import_vue6.defineComponent)({
408
+ name: "MasonLink",
409
+ inheritAttrs: false,
410
+ props: {
411
+ tone: {
412
+ type: String,
413
+ default: "link"
414
+ },
415
+ underline: {
416
+ type: String,
417
+ default: "hover"
418
+ },
419
+ /** Adds `target="_blank"` and a safe `rel`. */
420
+ external: {
421
+ type: Boolean,
422
+ default: false
423
+ }
424
+ },
425
+ setup(props, { slots, attrs }) {
426
+ return () => {
427
+ const { class: attrClass, style: attrStyle, ...rest } = attrs;
428
+ const externalAttrs = props.external ? { target: "_blank", rel: "noreferrer noopener" } : null;
429
+ return (0, import_vue6.h)(
430
+ "a",
431
+ {
432
+ "data-mason-component": "link",
433
+ "data-tone": props.tone,
434
+ "data-underline": props.underline,
435
+ ...externalAttrs,
436
+ ...rest,
437
+ class: mergeClassName(attrClass),
438
+ style: [
439
+ linkStyle({ tone: props.tone, underline: props.underline }),
440
+ attrStyle
441
+ ]
442
+ },
443
+ slots.default?.()
444
+ );
445
+ };
446
+ }
447
+ });
448
+
449
+ // src/Button.ts
450
+ var import_vue8 = require("vue");
451
+
452
+ // src/Spinner.ts
453
+ var import_vue7 = require("vue");
454
+
455
+ // src/spinnerStyles.ts
456
+ var SIZE_DIMENSION = {
457
+ sm: cssVar("font.body.sm.size"),
458
+ md: cssVar("font.body.md.size"),
459
+ lg: cssVar("font.display.lg.size"),
460
+ inherit: "1em"
461
+ };
462
+ function spinnerStyle(size = "md") {
463
+ const dimension = SIZE_DIMENSION[size];
464
+ return {
465
+ width: dimension,
466
+ height: dimension,
467
+ border: "2px solid currentColor",
468
+ borderTopColor: "transparent",
469
+ borderRadius: "50%",
470
+ display: "inline-block",
471
+ flexShrink: "0"
472
+ };
473
+ }
474
+
475
+ // src/Spinner.ts
476
+ var Spinner = (0, import_vue7.defineComponent)({
477
+ name: "MasonSpinner",
478
+ inheritAttrs: false,
479
+ props: {
480
+ size: {
481
+ type: String,
482
+ default: "md"
483
+ },
484
+ /** Announced while loading. Without it the spinner is `aria-hidden`. */
485
+ label: {
486
+ type: String,
487
+ default: void 0
488
+ }
489
+ },
490
+ setup(props, { attrs }) {
491
+ return () => {
492
+ const { class: attrClass, style: attrStyle, ...rest } = attrs;
493
+ return (0, import_vue7.h)("span", {
494
+ ...rest,
495
+ "data-mason-component": "spinner",
496
+ "data-size": props.size,
497
+ role: props.label ? "status" : void 0,
498
+ "aria-label": props.label,
499
+ "aria-hidden": props.label ? void 0 : "true",
500
+ class: mergeClassName(attrClass),
501
+ style: [spinnerStyle(props.size), attrStyle]
502
+ });
503
+ };
504
+ }
505
+ });
506
+
507
+ // src/buttonStyles.ts
508
+ function actionColors(variant) {
509
+ return {
510
+ bg: `color.action.${variant}.bg`,
511
+ text: `color.action.${variant}.text`,
512
+ border: `color.action.${variant}.border`
513
+ };
514
+ }
515
+ var sizeStyles = {
516
+ sm: {
517
+ paddingBlock: cssVar("spacing.inset.sm"),
518
+ paddingInline: cssVar("spacing.inset.md"),
519
+ gap: cssVar("spacing.inline.sm"),
520
+ radius: cssVar("radius.sm"),
521
+ font: "label.sm"
522
+ },
523
+ md: {
524
+ paddingBlock: cssVar("spacing.inset.md"),
525
+ paddingInline: cssVar("spacing.inset.lg"),
526
+ gap: cssVar("spacing.inline.md"),
527
+ radius: cssVar("radius.md"),
528
+ font: "label.md"
529
+ },
530
+ lg: {
531
+ paddingBlock: cssVar("spacing.inset.lg"),
532
+ paddingInline: `calc(${cssVar("spacing.inset.lg")} + ${cssVar("spacing.inset.md")})`,
533
+ gap: cssVar("spacing.inline.md"),
534
+ radius: cssVar("radius.lg"),
535
+ font: "label.lg"
536
+ }
537
+ };
538
+ function buttonStyle({
539
+ variant = "primary",
540
+ size = "md",
541
+ disabled = false,
542
+ loading = false
543
+ }) {
544
+ const inactive = disabled || loading;
545
+ const colors = actionColors(inactive ? "disabled" : variant);
546
+ const sizing = sizeStyles[size];
547
+ return {
548
+ display: "inline-flex",
549
+ alignItems: "center",
550
+ justifyContent: "center",
551
+ gap: sizing.gap,
552
+ paddingBlock: sizing.paddingBlock,
553
+ paddingInline: sizing.paddingInline,
554
+ margin: "0",
555
+ backgroundColor: cssVar(colors.bg),
556
+ color: cssVar(colors.text),
557
+ border: `1px solid ${cssVar(colors.border)}`,
558
+ borderRadius: sizing.radius,
559
+ boxSizing: "border-box",
560
+ ...typographyStyle(sizing.font),
561
+ textDecoration: "none",
562
+ whiteSpace: "nowrap"
563
+ };
564
+ }
565
+
566
+ // src/Button.ts
567
+ var Button = (0, import_vue8.defineComponent)({
568
+ name: "MasonButton",
569
+ inheritAttrs: false,
570
+ props: {
571
+ variant: {
572
+ type: String,
573
+ default: "primary"
574
+ },
575
+ size: {
576
+ type: String,
577
+ default: "md"
578
+ },
579
+ loading: {
580
+ type: Boolean,
581
+ default: false
582
+ },
583
+ disabled: {
584
+ type: Boolean,
585
+ default: false
586
+ },
587
+ type: {
588
+ type: String,
589
+ default: "button"
590
+ }
591
+ },
592
+ setup(props, { slots, attrs }) {
593
+ const isDisabled = (0, import_vue8.computed)(() => props.disabled || props.loading);
594
+ return () => {
595
+ const children = [];
596
+ if (props.loading) {
597
+ children.push((0, import_vue8.h)(Spinner, { size: "inherit", "data-mason-slot": "spinner" }));
598
+ } else if (slots.leading) {
599
+ children.push((0, import_vue8.h)("span", { "data-mason-slot": "leading" }, slots.leading()));
600
+ }
601
+ if (slots.default) {
602
+ children.push((0, import_vue8.h)("span", { "data-mason-slot": "label" }, slots.default()));
603
+ }
604
+ if (slots.trailing && !props.loading) {
605
+ children.push((0, import_vue8.h)("span", { "data-mason-slot": "trailing" }, slots.trailing()));
606
+ }
607
+ const attrClass = attrs.class;
608
+ const attrStyle = attrs.style;
609
+ return (0, import_vue8.h)(
610
+ "button",
611
+ {
612
+ ...attrs,
613
+ type: props.type,
614
+ "data-mason-component": "button",
615
+ "data-variant": props.variant,
616
+ "data-size": props.size,
617
+ disabled: isDisabled.value,
618
+ "aria-busy": props.loading || void 0,
619
+ class: mergeClassName(attrClass),
620
+ style: [
621
+ buttonStyle({
622
+ variant: props.variant,
623
+ size: props.size,
624
+ disabled: props.disabled,
625
+ loading: props.loading
626
+ }),
627
+ attrStyle
628
+ ]
629
+ },
630
+ children
631
+ );
632
+ };
633
+ }
634
+ });
635
+
636
+ // src/Badge.ts
637
+ var import_vue9 = require("vue");
638
+
639
+ // src/badgeStyles.ts
640
+ function badgeStyle({
641
+ tone = "neutral",
642
+ size = "sm"
643
+ }) {
644
+ const colors = tone === "neutral" ? {
645
+ bg: cssVar("color.bg.canvas"),
646
+ text: cssVar("color.text.secondary"),
647
+ border: cssVar("color.border.subtle")
648
+ } : {
649
+ bg: cssVar(`color.feedback.${tone}.bg`),
650
+ text: cssVar(`color.feedback.${tone}.text`),
651
+ border: cssVar(`color.feedback.${tone}.border`)
652
+ };
653
+ return {
654
+ display: "inline-flex",
655
+ alignItems: "center",
656
+ gap: spacingVar("inline", "sm"),
657
+ paddingBlock: "0.125em",
658
+ paddingInline: spacingVar("inset", "sm"),
659
+ backgroundColor: colors.bg,
660
+ color: colors.text,
661
+ border: `1px solid ${colors.border}`,
662
+ borderRadius: radiusVar("full"),
663
+ ...typographyStyle(size === "sm" ? "label.sm" : "label.md"),
664
+ whiteSpace: "nowrap"
665
+ };
666
+ }
667
+
668
+ // src/Badge.ts
669
+ var Badge = (0, import_vue9.defineComponent)({
670
+ name: "MasonBadge",
671
+ inheritAttrs: false,
672
+ props: {
673
+ tone: {
674
+ type: String,
675
+ default: "neutral"
676
+ },
677
+ size: {
678
+ type: String,
679
+ default: "sm"
680
+ }
681
+ },
682
+ setup(props, { slots, attrs }) {
683
+ return () => {
684
+ const { class: attrClass, style: attrStyle, ...rest } = attrs;
685
+ return (0, import_vue9.h)(
686
+ "span",
687
+ {
688
+ ...rest,
689
+ "data-mason-component": "badge",
690
+ "data-tone": props.tone,
691
+ "data-size": props.size,
692
+ class: mergeClassName(attrClass),
693
+ style: [
694
+ badgeStyle({ tone: props.tone, size: props.size }),
695
+ attrStyle
696
+ ]
697
+ },
698
+ slots.default?.()
699
+ );
700
+ };
701
+ }
702
+ });
703
+
704
+ // src/Callout.ts
705
+ var import_vue10 = require("vue");
706
+
707
+ // src/calloutStyles.ts
708
+ function calloutStyle(tone = "info") {
709
+ return {
710
+ display: "flex",
711
+ gap: spacingVar("inline", "md"),
712
+ padding: spacingVar("inset", "md"),
713
+ backgroundColor: cssVar(`color.feedback.${tone}.bg`),
714
+ color: cssVar(`color.feedback.${tone}.text`),
715
+ border: `1px solid ${cssVar(`color.feedback.${tone}.border`)}`,
716
+ borderRadius: radiusVar("md"),
717
+ boxSizing: "border-box",
718
+ ...typographyStyle("body.md")
719
+ };
720
+ }
721
+ function calloutContentStyle() {
722
+ return {
723
+ display: "flex",
724
+ flexDirection: "column",
725
+ gap: spacingVar("stack", "sm"),
726
+ minWidth: "0"
727
+ };
728
+ }
729
+ function calloutTitleStyle() {
730
+ return { margin: "0", ...typographyStyle("label.md") };
731
+ }
732
+ function calloutBodyStyle() {
733
+ return { margin: "0", ...typographyStyle("body.sm") };
734
+ }
735
+
736
+ // src/Callout.ts
737
+ var Callout = (0, import_vue10.defineComponent)({
738
+ name: "MasonCallout",
739
+ inheritAttrs: false,
740
+ props: {
741
+ tone: {
742
+ type: String,
743
+ default: "info"
744
+ },
745
+ /** Heading text; the `title` slot takes precedence. */
746
+ title: {
747
+ type: String,
748
+ default: void 0
749
+ }
750
+ },
751
+ setup(props, { slots, attrs }) {
752
+ return () => {
753
+ const { class: attrClass, style: attrStyle, ...rest } = attrs;
754
+ const title = slots.title?.() ?? props.title;
755
+ const body = slots.default?.();
756
+ const content = [];
757
+ if (title) {
758
+ content.push(
759
+ (0, import_vue10.h)("p", { "data-mason-slot": "title", style: calloutTitleStyle() }, title)
760
+ );
761
+ }
762
+ if (body) {
763
+ content.push(
764
+ (0, import_vue10.h)("div", { "data-mason-slot": "body", style: calloutBodyStyle() }, body)
765
+ );
766
+ }
767
+ const children = [];
768
+ if (slots.icon) {
769
+ children.push(
770
+ (0, import_vue10.h)(
771
+ "span",
772
+ { "data-mason-slot": "icon", "aria-hidden": "true" },
773
+ slots.icon()
774
+ )
775
+ );
776
+ }
777
+ children.push(
778
+ (0, import_vue10.h)(
779
+ "div",
780
+ { "data-mason-slot": "content", style: calloutContentStyle() },
781
+ content
782
+ )
783
+ );
784
+ return (0, import_vue10.h)(
785
+ "div",
786
+ {
787
+ ...rest,
788
+ "data-mason-component": "callout",
789
+ "data-tone": props.tone,
790
+ class: mergeClassName(attrClass),
791
+ style: [calloutStyle(props.tone), attrStyle]
792
+ },
793
+ children
794
+ );
795
+ };
796
+ }
797
+ });
798
+
799
+ // src/TextField.ts
800
+ var import_vue12 = require("vue");
801
+
802
+ // src/field.ts
803
+ var import_vue11 = require("vue");
804
+
805
+ // src/fieldStyles.ts
806
+ var CONTROL_FONT = {
807
+ sm: "body.sm",
808
+ md: "body.md",
809
+ lg: "body.lg"
810
+ };
811
+ var LABEL_FONT = {
812
+ sm: "label.sm",
813
+ md: "label.md",
814
+ lg: "label.lg"
815
+ };
816
+ var CONTROL_PADDING_BLOCK = { sm: "sm", md: "sm", lg: "md" };
817
+ var CONTROL_PADDING_INLINE = { sm: "sm", md: "md", lg: "md" };
818
+ function fieldRootStyle() {
819
+ return {
820
+ display: "flex",
821
+ flexDirection: "column",
822
+ gap: spacingVar("stack", "sm"),
823
+ minWidth: "0"
824
+ };
825
+ }
826
+ function fieldLabelStyle(size = "md") {
827
+ return {
828
+ color: cssVar("color.text.primary"),
829
+ ...typographyStyle(LABEL_FONT[size])
830
+ };
831
+ }
832
+ function fieldControlStyle({
833
+ size = "md",
834
+ invalid = false,
835
+ disabled = false
836
+ }) {
837
+ return {
838
+ width: "100%",
839
+ boxSizing: "border-box",
840
+ margin: "0",
841
+ paddingBlock: spacingVar("inset", CONTROL_PADDING_BLOCK[size]),
842
+ paddingInline: spacingVar("inset", CONTROL_PADDING_INLINE[size]),
843
+ backgroundColor: disabled ? cssVar("color.action.disabled.bg") : cssVar("color.field.bg"),
844
+ color: disabled ? cssVar("color.text.disabled") : cssVar("color.field.text"),
845
+ border: `1px solid ${cssVar(
846
+ invalid ? "color.field.borderInvalid" : "color.field.border"
847
+ )}`,
848
+ borderRadius: radiusVar("md"),
849
+ ...typographyStyle(CONTROL_FONT[size])
850
+ };
851
+ }
852
+ function fieldDescriptionStyle() {
853
+ return {
854
+ margin: "0",
855
+ color: cssVar("color.text.secondary"),
856
+ ...typographyStyle("body.sm")
857
+ };
858
+ }
859
+ function fieldErrorStyle() {
860
+ return {
861
+ margin: "0",
862
+ color: cssVar("color.text.danger"),
863
+ ...typographyStyle("body.sm")
864
+ };
865
+ }
866
+
867
+ // src/field.ts
868
+ var fieldSeq = 0;
869
+ function nextFieldId() {
870
+ fieldSeq += 1;
871
+ return `mason-field-${fieldSeq}`;
872
+ }
873
+ function fieldIds(controlId, hasDescription, hasError) {
874
+ const descriptionId = `${controlId}-description`;
875
+ const errorId = `${controlId}-error`;
876
+ return {
877
+ controlId,
878
+ descriptionId,
879
+ errorId,
880
+ describedBy: [hasDescription ? descriptionId : null, hasError ? errorId : null].filter(Boolean).join(" ") || void 0
881
+ };
882
+ }
883
+ function renderFieldFrame({
884
+ component,
885
+ ids,
886
+ size,
887
+ invalid,
888
+ disabled,
889
+ label,
890
+ description,
891
+ error,
892
+ attrClass,
893
+ attrStyle,
894
+ control
895
+ }) {
896
+ const children = [];
897
+ if (label) {
898
+ children.push(
899
+ (0, import_vue11.h)(
900
+ "label",
901
+ {
902
+ "data-mason-slot": "label",
903
+ for: ids.controlId,
904
+ style: fieldLabelStyle(size)
905
+ },
906
+ label
907
+ )
908
+ );
909
+ }
910
+ children.push(control);
911
+ if (description) {
912
+ children.push(
913
+ (0, import_vue11.h)(
914
+ "p",
915
+ {
916
+ "data-mason-slot": "description",
917
+ id: ids.descriptionId,
918
+ style: fieldDescriptionStyle()
919
+ },
920
+ description
921
+ )
922
+ );
923
+ }
924
+ if (error) {
925
+ children.push(
926
+ (0, import_vue11.h)(
927
+ "p",
928
+ {
929
+ "data-mason-slot": "error",
930
+ id: ids.errorId,
931
+ role: "alert",
932
+ style: fieldErrorStyle()
933
+ },
934
+ error
935
+ )
936
+ );
937
+ }
938
+ return (0, import_vue11.h)(
939
+ "div",
940
+ {
941
+ "data-mason-component": component,
942
+ "data-size": size,
943
+ "data-invalid": invalid || void 0,
944
+ "data-disabled": disabled || void 0,
945
+ class: mergeClassName(attrClass),
946
+ style: [fieldRootStyle(), attrStyle]
947
+ },
948
+ children
949
+ );
950
+ }
951
+
952
+ // src/TextField.ts
953
+ var TextField = (0, import_vue12.defineComponent)({
954
+ name: "MasonTextField",
955
+ inheritAttrs: false,
956
+ props: {
957
+ label: {
958
+ type: String,
959
+ default: void 0
960
+ },
961
+ description: {
962
+ type: String,
963
+ default: void 0
964
+ },
965
+ /** Present error text switches the field to its invalid styling. */
966
+ error: {
967
+ type: String,
968
+ default: void 0
969
+ },
970
+ size: {
971
+ type: String,
972
+ default: "md"
973
+ },
974
+ invalid: {
975
+ type: Boolean,
976
+ default: void 0
977
+ },
978
+ disabled: {
979
+ type: Boolean,
980
+ default: false
981
+ },
982
+ id: {
983
+ type: String,
984
+ default: void 0
985
+ },
986
+ modelValue: {
987
+ type: String,
988
+ default: void 0
989
+ }
990
+ },
991
+ emits: ["update:modelValue"],
992
+ setup(props, { slots, attrs, emit }) {
993
+ const autoId = nextFieldId();
994
+ return () => {
995
+ const {
996
+ class: attrClass,
997
+ style: attrStyle,
998
+ onInput: attrInput,
999
+ ...controlAttrs
1000
+ } = attrs;
1001
+ const label = slots.label?.() ?? props.label;
1002
+ const description = slots.description?.() ?? props.description;
1003
+ const error = slots.error?.() ?? props.error;
1004
+ const invalid = props.invalid ?? Boolean(error);
1005
+ const ids = fieldIds(props.id ?? autoId, Boolean(description), Boolean(error));
1006
+ const emitInput = (event) => {
1007
+ emit("update:modelValue", event.target.value);
1008
+ };
1009
+ const forwarded = attrInput;
1010
+ const control = (0, import_vue12.h)("input", {
1011
+ ...controlAttrs,
1012
+ id: ids.controlId,
1013
+ "data-mason-slot": "control",
1014
+ disabled: props.disabled,
1015
+ "aria-invalid": invalid || void 0,
1016
+ "aria-describedby": ids.describedBy,
1017
+ ...props.modelValue === void 0 ? null : { value: props.modelValue },
1018
+ onInput: forwarded ? [emitInput, forwarded] : emitInput,
1019
+ style: fieldControlStyle({
1020
+ size: props.size,
1021
+ invalid,
1022
+ disabled: props.disabled
1023
+ })
1024
+ });
1025
+ return renderFieldFrame({
1026
+ component: "text-field",
1027
+ ids,
1028
+ size: props.size,
1029
+ invalid,
1030
+ disabled: props.disabled,
1031
+ label,
1032
+ description,
1033
+ error,
1034
+ attrClass,
1035
+ attrStyle,
1036
+ control
1037
+ });
1038
+ };
1039
+ }
1040
+ });
1041
+
1042
+ // src/Select.ts
1043
+ var import_vue13 = require("vue");
1044
+ var Select = (0, import_vue13.defineComponent)({
1045
+ name: "MasonSelect",
1046
+ inheritAttrs: false,
1047
+ props: {
1048
+ label: {
1049
+ type: String,
1050
+ default: void 0
1051
+ },
1052
+ description: {
1053
+ type: String,
1054
+ default: void 0
1055
+ },
1056
+ error: {
1057
+ type: String,
1058
+ default: void 0
1059
+ },
1060
+ size: {
1061
+ type: String,
1062
+ default: "md"
1063
+ },
1064
+ invalid: {
1065
+ type: Boolean,
1066
+ default: void 0
1067
+ },
1068
+ disabled: {
1069
+ type: Boolean,
1070
+ default: false
1071
+ },
1072
+ id: {
1073
+ type: String,
1074
+ default: void 0
1075
+ },
1076
+ /** Rendered as a leading empty `<option>`. */
1077
+ placeholder: {
1078
+ type: String,
1079
+ default: void 0
1080
+ },
1081
+ modelValue: {
1082
+ type: String,
1083
+ default: void 0
1084
+ }
1085
+ },
1086
+ emits: ["update:modelValue"],
1087
+ setup(props, { slots, attrs, emit }) {
1088
+ const autoId = nextFieldId();
1089
+ return () => {
1090
+ const {
1091
+ class: attrClass,
1092
+ style: attrStyle,
1093
+ onChange: attrChange,
1094
+ ...controlAttrs
1095
+ } = attrs;
1096
+ const label = slots.label?.() ?? props.label;
1097
+ const description = slots.description?.() ?? props.description;
1098
+ const error = slots.error?.() ?? props.error;
1099
+ const invalid = props.invalid ?? Boolean(error);
1100
+ const ids = fieldIds(props.id ?? autoId, Boolean(description), Boolean(error));
1101
+ const emitChange = (event) => {
1102
+ emit("update:modelValue", event.target.value);
1103
+ };
1104
+ const forwarded = attrChange;
1105
+ const options = [];
1106
+ if (props.placeholder) {
1107
+ options.push((0, import_vue13.h)("option", { value: "" }, props.placeholder));
1108
+ }
1109
+ const provided = slots.default?.();
1110
+ if (provided) {
1111
+ options.push(provided);
1112
+ }
1113
+ const control = (0, import_vue13.h)(
1114
+ "select",
1115
+ {
1116
+ ...controlAttrs,
1117
+ id: ids.controlId,
1118
+ "data-mason-slot": "control",
1119
+ disabled: props.disabled,
1120
+ "aria-invalid": invalid || void 0,
1121
+ "aria-describedby": ids.describedBy,
1122
+ ...props.modelValue === void 0 ? null : { value: props.modelValue },
1123
+ onChange: forwarded ? [emitChange, forwarded] : emitChange,
1124
+ style: fieldControlStyle({
1125
+ size: props.size,
1126
+ invalid,
1127
+ disabled: props.disabled
1128
+ })
1129
+ },
1130
+ options
1131
+ );
1132
+ return renderFieldFrame({
1133
+ component: "select",
1134
+ ids,
1135
+ size: props.size,
1136
+ invalid,
1137
+ disabled: props.disabled,
1138
+ label,
1139
+ description,
1140
+ error,
1141
+ attrClass,
1142
+ attrStyle,
1143
+ control
1144
+ });
1145
+ };
1146
+ }
1147
+ });
1148
+
1149
+ // src/Checkbox.ts
1150
+ var import_vue14 = require("vue");
1151
+
1152
+ // src/checkboxStyles.ts
1153
+ function checkboxRootStyle() {
1154
+ return {
1155
+ display: "flex",
1156
+ flexDirection: "column",
1157
+ gap: spacingVar("stack", "sm"),
1158
+ minWidth: "0"
1159
+ };
1160
+ }
1161
+ function checkboxLabelStyle(disabled = false) {
1162
+ return {
1163
+ display: "inline-flex",
1164
+ alignItems: "flex-start",
1165
+ gap: spacingVar("inline", "sm"),
1166
+ cursor: disabled ? "not-allowed" : "pointer",
1167
+ color: disabled ? cssVar("color.text.disabled") : cssVar("color.text.primary"),
1168
+ ...typographyStyle("body.md")
1169
+ };
1170
+ }
1171
+ function checkboxControlStyle() {
1172
+ return {
1173
+ width: "1em",
1174
+ height: "1em",
1175
+ margin: "0",
1176
+ marginBlockStart: "0.15em",
1177
+ accentColor: cssVar("color.action.primary.bg"),
1178
+ flexShrink: "0"
1179
+ };
1180
+ }
1181
+
1182
+ // src/Checkbox.ts
1183
+ var Checkbox = (0, import_vue14.defineComponent)({
1184
+ name: "MasonCheckbox",
1185
+ inheritAttrs: false,
1186
+ props: {
1187
+ label: {
1188
+ type: String,
1189
+ default: void 0
1190
+ },
1191
+ description: {
1192
+ type: String,
1193
+ default: void 0
1194
+ },
1195
+ error: {
1196
+ type: String,
1197
+ default: void 0
1198
+ },
1199
+ invalid: {
1200
+ type: Boolean,
1201
+ default: void 0
1202
+ },
1203
+ disabled: {
1204
+ type: Boolean,
1205
+ default: false
1206
+ },
1207
+ id: {
1208
+ type: String,
1209
+ default: void 0
1210
+ },
1211
+ modelValue: {
1212
+ type: Boolean,
1213
+ default: void 0
1214
+ }
1215
+ },
1216
+ emits: ["update:modelValue"],
1217
+ setup(props, { slots, attrs, emit }) {
1218
+ const autoId = nextFieldId();
1219
+ return () => {
1220
+ const {
1221
+ class: attrClass,
1222
+ style: attrStyle,
1223
+ onChange: attrChange,
1224
+ ...controlAttrs
1225
+ } = attrs;
1226
+ const label = slots.label?.() ?? props.label;
1227
+ const description = slots.description?.() ?? props.description;
1228
+ const error = slots.error?.() ?? props.error;
1229
+ const invalid = props.invalid ?? Boolean(error);
1230
+ const ids = fieldIds(props.id ?? autoId, Boolean(description), Boolean(error));
1231
+ const emitChange = (event) => {
1232
+ emit("update:modelValue", event.target.checked);
1233
+ };
1234
+ const forwarded = attrChange;
1235
+ const children = [
1236
+ (0, import_vue14.h)(
1237
+ "label",
1238
+ {
1239
+ "data-mason-slot": "label",
1240
+ for: ids.controlId,
1241
+ style: checkboxLabelStyle(props.disabled)
1242
+ },
1243
+ [
1244
+ (0, import_vue14.h)("input", {
1245
+ ...controlAttrs,
1246
+ type: "checkbox",
1247
+ id: ids.controlId,
1248
+ "data-mason-slot": "control",
1249
+ disabled: props.disabled,
1250
+ "aria-invalid": invalid || void 0,
1251
+ "aria-describedby": ids.describedBy,
1252
+ ...props.modelValue === void 0 ? null : { checked: props.modelValue },
1253
+ onChange: forwarded ? [emitChange, forwarded] : emitChange,
1254
+ style: checkboxControlStyle()
1255
+ }),
1256
+ label ? (0, import_vue14.h)("span", { "data-mason-slot": "label-text" }, label) : null
1257
+ ]
1258
+ )
1259
+ ];
1260
+ if (description) {
1261
+ children.push(
1262
+ (0, import_vue14.h)(
1263
+ "p",
1264
+ {
1265
+ "data-mason-slot": "description",
1266
+ id: ids.descriptionId,
1267
+ style: fieldDescriptionStyle()
1268
+ },
1269
+ description
1270
+ )
1271
+ );
1272
+ }
1273
+ if (error) {
1274
+ children.push(
1275
+ (0, import_vue14.h)(
1276
+ "p",
1277
+ {
1278
+ "data-mason-slot": "error",
1279
+ id: ids.errorId,
1280
+ role: "alert",
1281
+ style: fieldErrorStyle()
1282
+ },
1283
+ error
1284
+ )
1285
+ );
1286
+ }
1287
+ return (0, import_vue14.h)(
1288
+ "div",
1289
+ {
1290
+ "data-mason-component": "checkbox",
1291
+ "data-invalid": invalid || void 0,
1292
+ "data-disabled": props.disabled || void 0,
1293
+ class: mergeClassName(attrClass),
1294
+ style: [checkboxRootStyle(), attrStyle]
1295
+ },
1296
+ children
1297
+ );
1298
+ };
1299
+ }
1300
+ });
1301
+ // Annotate the CommonJS export names for ESM import in node:
1302
+ 0 && (module.exports = {
1303
+ Badge,
1304
+ Button,
1305
+ Callout,
1306
+ Card,
1307
+ Checkbox,
1308
+ Divider,
1309
+ Link,
1310
+ MasonProvider,
1311
+ Select,
1312
+ Spinner,
1313
+ Stack,
1314
+ Text,
1315
+ TextField
1316
+ });
1317
+ //# sourceMappingURL=index.cjs.map