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