@leaflink/stash 50.8.1 → 50.10.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,4 +1,4 @@
1
- import { defineComponent as p, useCssModule as _, useSlots as g, openBlock as s, createElementBlock as a, createBlock as y, createCommentVNode as i, createElementVNode as u, renderSlot as o, toDisplayString as m, normalizeClass as n, unref as r, createTextVNode as f } from "vue";
1
+ import { defineComponent as p, useCssModule as f, useSlots as _, openBlock as s, createElementBlock as o, createBlock as g, createCommentVNode as n, createElementVNode as u, renderSlot as a, toDisplayString as i, normalizeClass as m, unref as r, createTextVNode as y } from "vue";
2
2
  import { t as w } from "./locale.js";
3
3
  import { _ as b } from "./Illustration.vue_vue_type_script_setup_true_lang-CYddAFtS.js";
4
4
  import { _ as h } from "./_plugin-vue_export-helper-CHgC5LLL.js";
@@ -9,7 +9,7 @@ const x = {
9
9
  }, k = {
10
10
  key: 0,
11
11
  class: "tw-flex tw-flex-col tw-items-center tw-text-center md:tw-flex-row md:tw-text-left"
12
- }, v = { class: "tw-mb-1.5" }, S = ["alt", "src"], $ = /* @__PURE__ */ p({
12
+ }, v = { class: "tw-mb-1.5" }, $ = ["alt", "src"], S = /* @__PURE__ */ p({
13
13
  name: "ll-empty-state",
14
14
  __name: "EmptyState",
15
15
  props: {
@@ -20,46 +20,53 @@ const x = {
20
20
  text: { default: "" },
21
21
  title: { default: "" },
22
22
  subtitle: { default: "" },
23
+ footnote: { default: "" },
23
24
  vignette: { default: void 0 }
24
25
  },
25
26
  setup(d) {
26
- const t = d, c = _(), e = g();
27
- return (l, N) => (s(), a("div", x, [
28
- t.title || e.title || t.subtitle || e.subtitle || t.vignette ? (s(), a("div", k, [
29
- t.vignette ? (s(), y(b, {
27
+ const t = d, c = f(), e = _();
28
+ return (l, N) => (s(), o("div", x, [
29
+ t.title || e.title || t.subtitle || e.subtitle || t.vignette ? (s(), o("div", k, [
30
+ t.vignette ? (s(), g(b, {
30
31
  key: 0,
31
32
  "data-test": "stash-empty-state|illustration",
32
33
  type: "vignette",
33
34
  class: "tw-mx-3",
34
35
  name: t.vignette,
35
36
  size: 300
36
- }, null, 8, ["name"])) : i("", !0),
37
+ }, null, 8, ["name"])) : n("", !0),
37
38
  u("section", null, [
38
- o(l.$slots, "title", {}, () => [
39
- u("h3", v, m(t.title), 1)
39
+ a(l.$slots, "title", {}, () => [
40
+ u("h3", v, i(t.title), 1)
40
41
  ]),
41
- o(l.$slots, "subtitle", {}, () => [
42
- t.subtitle || e.subtitle ? (s(), a("p", {
42
+ a(l.$slots, "subtitle", {}, () => [
43
+ t.subtitle || e.subtitle ? (s(), o("p", {
43
44
  key: 0,
44
- class: n({ " tw-mb-8": e.button, "tw-mb-0": !e.button })
45
- }, m(t.subtitle), 3)) : i("", !0)
45
+ class: m({ "tw-mb-8": e.button, "tw-mb-0": !e.button })
46
+ }, i(t.subtitle), 3)) : n("", !0)
46
47
  ]),
47
- o(l.$slots, "button")
48
+ a(l.$slots, "button"),
49
+ a(l.$slots, "footnote", {}, () => [
50
+ t.footnote ? (s(), o("p", {
51
+ key: 0,
52
+ class: m(["tw-mb-0 tw-text-xs", { "tw-mt-3": e.button }])
53
+ }, i(t.footnote), 3)) : n("", !0)
54
+ ])
48
55
  ])
49
- ])) : (s(), a("div", {
56
+ ])) : (s(), o("div", {
50
57
  key: 1,
51
- class: n(["tw-mx-auto tw-my-0 tw-flex tw-items-center tw-justify-center tw-py-12", [r(c).root, { "tw-text-center": !t.image.src && !e.image }]])
58
+ class: m(["tw-mx-auto tw-my-0 tw-flex tw-items-center tw-justify-center tw-py-12", [r(c).root, { "tw-text-center": !t.image.src && !e.image }]])
52
59
  }, [
53
- o(l.$slots, "image", {}, () => [
54
- t.image.src ? (s(), a("img", {
60
+ a(l.$slots, "image", {}, () => [
61
+ t.image.src ? (s(), o("img", {
55
62
  key: 0,
56
- class: n(["tw-mr-6", r(c).image]),
63
+ class: m(["tw-mr-6", r(c).image]),
57
64
  alt: t.image.alt,
58
65
  src: t.image.src,
59
66
  "data-test": "stash-empty-state__img"
60
- }, null, 10, S)) : i("", !0)
67
+ }, null, 10, $)) : n("", !0)
61
68
  ]),
62
- f(" " + m(t.text || r(w)("ll.emptyState.noResults")), 1)
69
+ y(" " + i(t.text || r(w)("ll.emptyState.noResults")), 1)
63
70
  ], 2))
64
71
  ]));
65
72
  }
@@ -68,7 +75,7 @@ const x = {
68
75
  image: E
69
76
  }, M = {
70
77
  $style: B
71
- }, R = /* @__PURE__ */ h($, [["__cssModules", M]]);
78
+ }, R = /* @__PURE__ */ h(S, [["__cssModules", M]]);
72
79
  export {
73
80
  R as default
74
81
  };
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.js","sources":["../src/components/EmptyState/EmptyState.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n import { useCssModule } from 'vue';\n\n import { t } from '../../locale';\n import { VignetteNames } from '../Illustration/Illustration.models';\n import Illustration from '../Illustration/Illustration.vue';\n\n export interface EmptyStateProps {\n /**\n * @deprecated Use illustration instead.\n */\n image?: {\n alt?: string;\n src: string;\n };\n\n /**\n * @deprecated Use title instead.\n */\n text?: string;\n\n /**\n * the title text of the empty state\n */\n title?: string;\n\n /**\n * the subtitle text of the empty state\n */\n subtitle?: string;\n\n /**\n * The name of the vignette illustration to render\n */\n vignette?: VignetteNames;\n }\n\n export interface EmptyStateSlots {\n title?: () => unknown;\n subtitle?: () => unknown;\n button?: () => unknown;\n image?: () => unknown;\n }\n\n defineOptions({\n name: 'll-empty-state',\n });\n\n const props = withDefaults(defineProps<EmptyStateProps>(), {\n /**\n * An optional image to render\n */\n image: () => ({\n alt: '',\n src: '',\n }),\n\n /**\n * The custom message to render\n */\n text: '',\n\n title: '',\n subtitle: '',\n vignette: undefined,\n });\n\n const classes = useCssModule();\n const slots = defineSlots<EmptyStateSlots>();\n</script>\n\n<template>\n <div key=\"empty\" class=\"stash-empty-state\" data-test=\"stash-empty-state\">\n <template v-if=\"props.title || slots.title || props.subtitle || slots.subtitle || props.vignette\">\n <div class=\"tw-flex tw-flex-col tw-items-center tw-text-center md:tw-flex-row md:tw-text-left\">\n <Illustration\n v-if=\"props.vignette\"\n data-test=\"stash-empty-state|illustration\"\n type=\"vignette\"\n class=\"tw-mx-3\"\n :name=\"props.vignette\"\n :size=\"300\"\n />\n <section>\n <slot name=\"title\">\n <h3 class=\"tw-mb-1.5\">\n {{ props.title }}\n </h3>\n </slot>\n\n <slot name=\"subtitle\">\n <p v-if=\"props.subtitle || slots.subtitle\" :class=\"{ ' tw-mb-8': slots.button, 'tw-mb-0': !slots.button }\">\n {{ props.subtitle }}\n </p>\n </slot>\n\n <slot name=\"button\"></slot>\n </section>\n </div>\n </template>\n\n <template v-else>\n <div\n class=\"tw-mx-auto tw-my-0 tw-flex tw-items-center tw-justify-center tw-py-12\"\n :class=\"[classes.root, { 'tw-text-center': !props.image.src && !slots.image }]\"\n >\n <slot name=\"image\">\n <img\n v-if=\"props.image.src\"\n class=\"tw-mr-6\"\n :alt=\"props.image.alt\"\n :class=\"classes.image\"\n :src=\"props.image.src\"\n data-test=\"stash-empty-state__img\"\n />\n </slot>\n\n {{ props.text || t('ll.emptyState.noResults') }}\n </div>\n </template>\n </div>\n</template>\n\n<style module>\n .root {\n max-width: 600px;\n }\n\n .image {\n max-width: 60px;\n }\n</style>\n"],"names":["props","__props","classes","useCssModule","slots","_useSlots"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAgDE,UAAMA,IAAQC,GAmBRC,IAAUC,EAAa,GACvBC,IAAQC,EAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"EmptyState.js","sources":["../src/components/EmptyState/EmptyState.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n import { useCssModule } from 'vue';\n\n import { t } from '../../locale';\n import { VignetteNames } from '../Illustration/Illustration.models';\n import Illustration from '../Illustration/Illustration.vue';\n\n export interface EmptyStateProps {\n /**\n * @deprecated Use illustration instead.\n */\n image?: {\n alt?: string;\n src: string;\n };\n\n /**\n * @deprecated Use title instead.\n */\n text?: string;\n\n /**\n * the title text of the empty state\n */\n title?: string;\n\n /**\n * the subtitle text of the empty state\n */\n subtitle?: string;\n\n /**\n * additional text to place at the bottom of the empty state\n */\n footnote?: string;\n\n /**\n * The name of the vignette illustration to render\n */\n vignette?: VignetteNames;\n }\n\n export interface EmptyStateSlots {\n title?: () => unknown;\n subtitle?: () => unknown;\n footnote?: () => unknown;\n button?: () => unknown;\n image?: () => unknown;\n }\n\n defineOptions({\n name: 'll-empty-state',\n });\n\n const props = withDefaults(defineProps<EmptyStateProps>(), {\n /**\n * An optional image to render\n */\n image: () => ({\n alt: '',\n src: '',\n }),\n\n /**\n * The custom message to render\n */\n text: '',\n\n title: '',\n subtitle: '',\n footnote: '',\n vignette: undefined,\n });\n\n const classes = useCssModule();\n const slots = defineSlots<EmptyStateSlots>();\n</script>\n\n<template>\n <div key=\"empty\" class=\"stash-empty-state\" data-test=\"stash-empty-state\">\n <template v-if=\"props.title || slots.title || props.subtitle || slots.subtitle || props.vignette\">\n <div class=\"tw-flex tw-flex-col tw-items-center tw-text-center md:tw-flex-row md:tw-text-left\">\n <Illustration\n v-if=\"props.vignette\"\n data-test=\"stash-empty-state|illustration\"\n type=\"vignette\"\n class=\"tw-mx-3\"\n :name=\"props.vignette\"\n :size=\"300\"\n />\n <section>\n <slot name=\"title\">\n <h3 class=\"tw-mb-1.5\">\n {{ props.title }}\n </h3>\n </slot>\n\n <slot name=\"subtitle\">\n <p v-if=\"props.subtitle || slots.subtitle\" :class=\"{ 'tw-mb-8': slots.button, 'tw-mb-0': !slots.button }\">\n {{ props.subtitle }}\n </p>\n </slot>\n\n <slot name=\"button\"></slot>\n <slot name=\"footnote\">\n <p v-if=\"props.footnote\" class=\"tw-mb-0 tw-text-xs\" :class=\"{ 'tw-mt-3': slots.button }\">\n {{ props.footnote }}\n </p>\n </slot>\n </section>\n </div>\n </template>\n\n <template v-else>\n <div\n class=\"tw-mx-auto tw-my-0 tw-flex tw-items-center tw-justify-center tw-py-12\"\n :class=\"[classes.root, { 'tw-text-center': !props.image.src && !slots.image }]\"\n >\n <slot name=\"image\">\n <img\n v-if=\"props.image.src\"\n class=\"tw-mr-6\"\n :alt=\"props.image.alt\"\n :class=\"classes.image\"\n :src=\"props.image.src\"\n data-test=\"stash-empty-state__img\"\n />\n </slot>\n\n {{ props.text || t('ll.emptyState.noResults') }}\n </div>\n </template>\n </div>\n</template>\n\n<style module>\n .root {\n max-width: 600px;\n }\n\n .image {\n max-width: 60px;\n }\n</style>\n"],"names":["props","__props","classes","useCssModule","slots","_useSlots"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAsDE,UAAMA,IAAQC,GAoBRC,IAAUC,EAAa,GACvBC,IAAQC,EAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -46,6 +46,7 @@ src: string;
46
46
  text: string;
47
47
  title: string;
48
48
  subtitle: string;
49
+ footnote: string;
49
50
  vignette: undefined;
50
51
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<EmptyStateProps>, {
51
52
  /**
@@ -61,6 +62,7 @@ src: string;
61
62
  text: string;
62
63
  title: string;
63
64
  subtitle: string;
65
+ footnote: string;
64
66
  vignette: undefined;
65
67
  }>>> & Readonly<{}>, {
66
68
  title: string;
@@ -71,6 +73,7 @@ src: string;
71
73
  text: string;
72
74
  subtitle: string;
73
75
  vignette: "map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery";
76
+ footnote: string;
74
77
  }, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>, Readonly<EmptyStateSlots> & EmptyStateSlots>;
75
78
  export default _default;
76
79
 
@@ -94,6 +97,10 @@ export declare interface EmptyStateProps {
94
97
  * the subtitle text of the empty state
95
98
  */
96
99
  subtitle?: string;
100
+ /**
101
+ * additional text to place at the bottom of the empty state
102
+ */
103
+ footnote?: string;
97
104
  /**
98
105
  * The name of the vignette illustration to render
99
106
  */
@@ -103,6 +110,7 @@ export declare interface EmptyStateProps {
103
110
  export declare interface EmptyStateSlots {
104
111
  title?: () => unknown;
105
112
  subtitle?: () => unknown;
113
+ footnote?: () => unknown;
106
114
  button?: () => unknown;
107
115
  image?: () => unknown;
108
116
  }
@@ -3489,6 +3489,10 @@ vignette: {
3489
3489
  type: PropType<"map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery">;
3490
3490
  default: undefined;
3491
3491
  };
3492
+ footnote: {
3493
+ type: PropType<string>;
3494
+ default: string;
3495
+ };
3492
3496
  }>> & Readonly<{}>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, PublicProps, {
3493
3497
  title: string;
3494
3498
  image: {
@@ -3498,6 +3502,7 @@ src: string;
3498
3502
  text: string;
3499
3503
  subtitle: string;
3500
3504
  vignette: "map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery";
3505
+ footnote: string;
3501
3506
  }, true, {}, {}, GlobalComponents, GlobalDirectives, string, {}, any, ComponentProvideOptions, {
3502
3507
  P: {};
3503
3508
  B: {};
@@ -3532,6 +3537,10 @@ vignette: {
3532
3537
  type: PropType<"map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery">;
3533
3538
  default: undefined;
3534
3539
  };
3540
+ footnote: {
3541
+ type: PropType<string>;
3542
+ default: string;
3543
+ };
3535
3544
  }>> & Readonly<{}>, {}, {}, {}, {}, {
3536
3545
  title: string;
3537
3546
  image: {
@@ -3541,6 +3550,7 @@ src: string;
3541
3550
  text: string;
3542
3551
  subtitle: string;
3543
3552
  vignette: "map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery";
3553
+ footnote: string;
3544
3554
  }>;
3545
3555
  __isFragment?: undefined;
3546
3556
  __isTeleport?: undefined;
@@ -3572,6 +3582,10 @@ vignette: {
3572
3582
  type: PropType<"map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery">;
3573
3583
  default: undefined;
3574
3584
  };
3585
+ footnote: {
3586
+ type: PropType<string>;
3587
+ default: string;
3588
+ };
3575
3589
  }>> & Readonly<{}>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, {
3576
3590
  title: string;
3577
3591
  image: {
@@ -3581,6 +3595,7 @@ src: string;
3581
3595
  text: string;
3582
3596
  subtitle: string;
3583
3597
  vignette: "map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery";
3598
+ footnote: string;
3584
3599
  }, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & VNodeProps & AllowedComponentProps & ComponentCustomProps & (new () => {
3585
3600
  $slots: Readonly<EmptyStateSlots> & EmptyStateSlots;
3586
3601
  });
@@ -4687,6 +4702,7 @@ declare type DropdownOffset = {
4687
4702
  declare interface EmptyStateSlots {
4688
4703
  title?: () => unknown;
4689
4704
  subtitle?: () => unknown;
4705
+ footnote?: () => unknown;
4690
4706
  button?: () => unknown;
4691
4707
  image?: () => unknown;
4692
4708
  }
@@ -5253,6 +5269,10 @@ vignette: {
5253
5269
  type: PropType<"map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery">;
5254
5270
  default: undefined;
5255
5271
  };
5272
+ footnote: {
5273
+ type: PropType<string>;
5274
+ default: string;
5275
+ };
5256
5276
  }>> & Readonly<{}>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, PublicProps, {
5257
5277
  title: string;
5258
5278
  image: {
@@ -5262,6 +5282,7 @@ src: string;
5262
5282
  text: string;
5263
5283
  subtitle: string;
5264
5284
  vignette: "map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery";
5285
+ footnote: string;
5265
5286
  }, true, {}, {}, GlobalComponents, GlobalDirectives, string, {}, any, ComponentProvideOptions, {
5266
5287
  P: {};
5267
5288
  B: {};
@@ -5296,6 +5317,10 @@ vignette: {
5296
5317
  type: PropType<"map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery">;
5297
5318
  default: undefined;
5298
5319
  };
5320
+ footnote: {
5321
+ type: PropType<string>;
5322
+ default: string;
5323
+ };
5299
5324
  }>> & Readonly<{}>, {}, {}, {}, {}, {
5300
5325
  title: string;
5301
5326
  image: {
@@ -5305,6 +5330,7 @@ src: string;
5305
5330
  text: string;
5306
5331
  subtitle: string;
5307
5332
  vignette: "map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery";
5333
+ footnote: string;
5308
5334
  }>;
5309
5335
  __isFragment?: undefined;
5310
5336
  __isTeleport?: undefined;
@@ -5336,6 +5362,10 @@ vignette: {
5336
5362
  type: PropType<"map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery">;
5337
5363
  default: undefined;
5338
5364
  };
5365
+ footnote: {
5366
+ type: PropType<string>;
5367
+ default: string;
5368
+ };
5339
5369
  }>> & Readonly<{}>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, {
5340
5370
  title: string;
5341
5371
  image: {
@@ -5345,6 +5375,7 @@ src: string;
5345
5375
  text: string;
5346
5376
  subtitle: string;
5347
5377
  vignette: "map" | "search" | "calendar" | "dashboard" | "edit" | "megaphone" | "truck" | "warehouse" | "payments" | "light-bulb" | "messages" | "pie-chart" | "api" | "bank" | "basket" | "brand-menu" | "deals" | "document-search" | "empty-tray" | "graph" | "integrations" | "money-bank" | "notifications" | "orders-empty" | "product-cards" | "product-display" | "search-storefront" | "store" | "todo" | "users" | "warehouse-delivery";
5378
+ footnote: string;
5348
5379
  }, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & VNodeProps & AllowedComponentProps & ComponentCustomProps & (new () => {
5349
5380
  $slots: Readonly<EmptyStateSlots> & EmptyStateSlots;
5350
5381
  });
package/dist/Textarea.js CHANGED
@@ -1,7 +1,7 @@
1
- import { defineComponent as E, useAttrs as M, useSlots as k, useCssModule as H, ref as w, computed as x, watch as A, onMounted as I, nextTick as P, onBeforeUnmount as V, openBlock as $, createBlock as q, mergeProps as y, unref as p, createSlots as D, withCtx as b, createElementVNode as j, renderSlot as F } from "vue";
1
+ import { defineComponent as E, useAttrs as M, useSlots as k, useCssModule as H, ref as x, computed as w, watch as A, onMounted as I, nextTick as P, onBeforeUnmount as V, openBlock as $, createBlock as q, mergeProps as y, unref as p, createSlots as D, withCtx as b, createElementVNode as j, renderSlot as F } from "vue";
2
2
  import { _ as L } from "./Field.vue_vue_type_script_setup_true_lang-DEizIcDo.js";
3
3
  import { _ as N } from "./_plugin-vue_export-helper-CHgC5LLL.js";
4
- const U = ["id", "value", "placeholder", "disabled", "readonly", "rows"], W = /* @__PURE__ */ E({
4
+ const U = ["id", "maxlength", "value", "placeholder", "disabled", "readonly", "rows"], W = /* @__PURE__ */ E({
5
5
  name: "ll-textarea",
6
6
  __name: "Textarea",
7
7
  props: {
@@ -9,7 +9,8 @@ const U = ["id", "value", "placeholder", "disabled", "readonly", "rows"], W = /*
9
9
  value: { default: null },
10
10
  resize: { type: [Boolean, Object], default: !1 },
11
11
  placeholder: { default: void 0 },
12
- rows: {},
12
+ rows: { default: void 0 },
13
+ maxlength: { default: void 0 },
13
14
  addBottomSpace: { type: Boolean },
14
15
  errorText: {},
15
16
  hintText: {},
@@ -25,7 +26,7 @@ const U = ["id", "value", "placeholder", "disabled", "readonly", "rows"], W = /*
25
26
  },
26
27
  emits: ["update:model-value"],
27
28
  setup(_, { emit: g }) {
28
- const c = M(), B = k(), m = H(), t = _, z = g, u = w(), l = w(), R = x(() => t.isReadOnly || "readonly" in c && c.readonly !== !1), T = x(() => {
29
+ const c = M(), B = k(), m = H(), t = _, z = g, u = x(), r = x(), R = w(() => t.isReadOnly || "readonly" in c && c.readonly !== !1), T = w(() => {
29
30
  const e = { ...c };
30
31
  return delete e["data-test"], delete e.class, e;
31
32
  });
@@ -33,26 +34,26 @@ const U = ["id", "value", "placeholder", "disabled", "readonly", "rows"], W = /*
33
34
  () => t.resize,
34
35
  (e) => {
35
36
  var o;
36
- e ? h() : (o = l.value) == null || o.disconnect();
37
+ e ? h() : (o = r.value) == null || o.disconnect();
37
38
  }
38
39
  );
39
40
  const O = (e) => {
40
41
  z("update:model-value", e.target.value);
41
42
  }, h = () => {
42
- l.value || !u.value || (l.value = new ResizeObserver(([e]) => {
43
+ r.value || !u.value || (r.value = new ResizeObserver(([e]) => {
43
44
  const { target: o } = e, s = v(u.value) || document.documentElement, { scrollTop: a } = s;
44
45
  let n = 0;
45
46
  if (s === document.documentElement) {
46
- const { top: r, height: i } = C(o), { innerHeight: d } = window;
47
- n = Math.max(r + i - (d + a), 0);
47
+ const { top: l, height: i } = C(o), { innerHeight: d } = window;
48
+ n = Math.max(l + i - (d + a), 0);
48
49
  } else {
49
- const { top: r, height: i } = o.getBoundingClientRect(), { top: d } = s.getBoundingClientRect(), { offsetHeight: f } = s, S = r - d;
50
+ const { top: l, height: i } = o.getBoundingClientRect(), { top: d } = s.getBoundingClientRect(), { offsetHeight: f } = s, S = l - d;
50
51
  n = Math.max(S + i - f, 0);
51
52
  }
52
53
  n && requestAnimationFrame(() => {
53
54
  s.scrollTop = a + n;
54
55
  });
55
- }), l.value.observe(u.value));
56
+ }), r.value.observe(u.value));
56
57
  }, v = (e) => {
57
58
  const o = e.parentElement;
58
59
  if (!o)
@@ -62,10 +63,10 @@ const U = ["id", "value", "placeholder", "disabled", "readonly", "rows"], W = /*
62
63
  }, C = (e) => {
63
64
  const { offsetWidth: o, offsetHeight: s } = e;
64
65
  let a = 0, n = 0;
65
- const r = function({ offsetLeft: i, offsetTop: d, offsetParent: f }) {
66
- a += i, n += d, f && r(f);
66
+ const l = function({ offsetLeft: i, offsetTop: d, offsetParent: f }) {
67
+ a += i, n += d, f && l(f);
67
68
  };
68
- return r(e), {
69
+ return l(e), {
69
70
  top: n,
70
71
  left: a,
71
72
  width: o,
@@ -81,7 +82,7 @@ const U = ["id", "value", "placeholder", "disabled", "readonly", "rows"], W = /*
81
82
  (typeof t.resize == "boolean" && t.resize || (e = t.resize) != null && e.forceBrowserScroll) && (await P(), h());
82
83
  }), V(() => {
83
84
  var e;
84
- (e = l.value) == null || e.disconnect();
85
+ (e = r.value) == null || e.disconnect();
85
86
  }), (e, o) => ($(), q(L, y(t, {
86
87
  class: ["stash-textarea", [p(m).root]],
87
88
  "data-test": "stash-textarea"
@@ -102,6 +103,7 @@ const U = ["id", "value", "placeholder", "disabled", "readonly", "rows"], W = /*
102
103
  "tw-resize-none": !t.resize
103
104
  }
104
105
  ],
106
+ maxlength: t.maxlength,
105
107
  value: t.modelValue,
106
108
  "data-test": "stash-textarea|textarea",
107
109
  placeholder: t.placeholder
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.js","sources":["../src/components/Textarea/Textarea.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n import { computed, nextTick, onBeforeUnmount, onMounted, ref, useAttrs, useCssModule, useSlots, watch } from 'vue';\n\n import { FieldProps } from '../Field/Field.types';\n import Field from '../Field/Field.vue';\n\n export interface TextareaResizeOptions {\n /**\n * It will automatically scroll the page down when it reaches the bottom of the viewport/element\n */\n forceBrowserScroll: boolean;\n }\n\n export interface TextAreaProps extends FieldProps {\n /**\n * Value for the textarea element.\n */\n modelValue?: string;\n\n /**\n * Deprecated. Use :model-value or v-model instead of :value.\n * @deprecated Use :model-value or v-model instead of :value.\n */\n value?: string | number | null;\n\n /**\n * Allow textarea to be resizable vertically.\n * Alternatively if you want to disable automatic scroll when resizing, you can set `{ forceBrowserScroll: false }`\n */\n resize?: boolean | TextareaResizeOptions;\n\n /**\n * Placeholder text for the textarea element.\n * **Note:** placeholders should be used to display examples; they should not be used as labels because they are not accessible as labels. If a real label cannot be used, use the `aria-label` attribute.\n */\n placeholder?: string;\n\n /**\n * Number of rows to display in the textarea.\n */\n rows?: number;\n }\n\n defineOptions({\n name: 'll-textarea',\n });\n\n const attrs = useAttrs();\n const slots = useSlots();\n const classes = useCssModule();\n\n const props = withDefaults(defineProps<TextAreaProps>(), {\n modelValue: '',\n value: null,\n resize: false,\n placeholder: undefined,\n });\n\n const emits = defineEmits<{\n /**\n * Emitted when the model value changes.\n */\n (e: 'update:model-value', value: string): void;\n }>();\n\n const textareaRef = ref<HTMLTextAreaElement>();\n const observer = ref<ResizeObserver>();\n const isReadOnly = computed(() => props.isReadOnly || ('readonly' in attrs && attrs.readonly !== false));\n\n const inputAttrs = computed(() => {\n const allAttrs = { ...attrs };\n\n delete allAttrs['data-test'];\n delete allAttrs.class;\n\n return allAttrs;\n });\n\n watch(\n () => props.resize,\n (v) => {\n v ? setupResizeObserver() : observer.value?.disconnect();\n },\n );\n\n const onInput = (event: Event) => {\n emits('update:model-value', (event.target as HTMLTextAreaElement).value);\n };\n\n const setupResizeObserver = () => {\n if (observer.value || !textareaRef.value) {\n return;\n }\n\n // the ResizeObserver will be in charge to detect if page needs to scroll when resizing the component\n observer.value = new ResizeObserver(([entry]) => {\n const { target } = entry;\n const parent = findParentScrollable(textareaRef.value as HTMLTextAreaElement) || document.documentElement;\n\n const { scrollTop: scrollPosition } = parent;\n let offsetDiff = 0;\n\n // checks if the closest parent element scrollable is the document page\n if (parent === document.documentElement) {\n const { top, height } = getOffsetClipRect(target as HTMLElement);\n const { innerHeight: viewportHeight } = window;\n\n offsetDiff = Math.max(top + height - (viewportHeight + scrollPosition), 0);\n } else {\n const { top, height } = (target as HTMLElement).getBoundingClientRect();\n const { top: parentTop } = parent.getBoundingClientRect();\n const { offsetHeight: parentHeight } = parent;\n const offsetTop = top - parentTop;\n\n offsetDiff = Math.max(offsetTop + height - parentHeight, 0);\n }\n\n if (offsetDiff) {\n requestAnimationFrame(() => {\n parent.scrollTop = scrollPosition + offsetDiff;\n });\n }\n });\n\n observer.value.observe(textareaRef.value);\n };\n\n /**\n * Retrieve the closest parent that has a scroll. Defaults to the document page.\n */\n const findParentScrollable = (el: HTMLElement): HTMLElement | null => {\n const parent = el.parentElement as HTMLElement;\n if (!parent) {\n return null;\n }\n\n const { overflowY } = getComputedStyle(parent);\n if (overflowY !== 'visible') {\n return parent;\n }\n\n if (parent === document.body) {\n return document.documentElement;\n }\n\n return findParentScrollable(parent);\n };\n\n /**\n * Retrieve element absolute positioning relative to the page.\n */\n const getOffsetClipRect = (el: HTMLElement) => {\n const { offsetWidth: width, offsetHeight: height } = el;\n\n let left = 0;\n let top = 0;\n\n const findPos = function ({ offsetLeft, offsetTop, offsetParent }: HTMLElement) {\n left += offsetLeft;\n top += offsetTop;\n\n if (offsetParent) {\n findPos(offsetParent as HTMLElement);\n }\n };\n\n findPos(el);\n\n return {\n top,\n left,\n width,\n height,\n };\n };\n\n onMounted(async () => {\n if (props.value !== null) {\n throw new Error('ll-input: use :model-value or v-model instead of :value.');\n }\n\n if (attrs.onInput) {\n throw new Error('ll-input: use the @update:model-value event instead of @input');\n }\n\n if (\n (typeof props.resize === 'boolean' && props.resize) ||\n (props.resize as TextareaResizeOptions)?.forceBrowserScroll\n ) {\n await nextTick();\n setupResizeObserver();\n }\n });\n\n onBeforeUnmount(() => {\n observer.value?.disconnect();\n });\n</script>\n\n<template>\n <Field v-bind=\"props\" class=\"stash-textarea\" :class=\"[classes.root]\" data-test=\"stash-textarea\">\n <template #default=\"{ fieldId, hasError }\">\n <textarea\n :id=\"fieldId\"\n ref=\"textareaRef\"\n :class=\"[\n classes.textarea,\n 'tw-border tw-border-ice-500',\n {\n 'stash-textarea--error tw-border-red-500 tw-text-red-500': hasError,\n 'tw-text-ice-700 hover:tw-border-ice-500 focus:tw-border-blue-500 active:tw-border-blue-500':\n !hasError && !props.disabled,\n 'tw-resize-y': props.resize,\n 'tw-min-h-[100px]': !props.rows,\n 'tw-resize-none': !props.resize,\n },\n ]\"\n :value=\"props.modelValue\"\n data-test=\"stash-textarea|textarea\"\n :placeholder=\"props.placeholder\"\n v-bind=\"inputAttrs\"\n :disabled=\"props.disabled\"\n :readonly=\"isReadOnly\"\n :rows=\"props.rows\"\n @input=\"onInput\"\n ></textarea>\n </template>\n <template v-if=\"slots.hint\" #hint>\n <!-- @slot Hint content -->\n <slot name=\"hint\"></slot>\n </template>\n </Field>\n</template>\n\n<style module>\n .root {\n position: relative;\n width: 100%;\n }\n\n .textarea {\n background: var(--color-white);\n border-radius: theme('borderRadius.DEFAULT');\n display: block;\n outline: none;\n padding: theme('spacing[1.5]');\n width: 100%;\n\n &::placeholder {\n color: var(--color-ice-500);\n opacity: 1;\n }\n\n &[disabled] {\n background-color: var(--color-ice-100);\n border-color: var(--color-ice-500);\n color: var(--color-ice-500);\n pointer-events: none;\n }\n\n &[disabled]:active,\n &[disabled]:focus {\n box-shadow: none;\n }\n\n &[disabled]::placeholder {\n text-transform: none;\n color: var(--color-ice-500);\n }\n\n &[readonly] {\n border-color: transparent;\n background-color: transparent;\n padding-left: 0;\n padding-right: 0;\n min-height: unset;\n }\n }\n</style>\n"],"names":["attrs","useAttrs","slots","useSlots","classes","useCssModule","props","__props","emits","__emit","textareaRef","ref","observer","isReadOnly","computed","inputAttrs","allAttrs","watch","v","setupResizeObserver","_a","onInput","event","entry","target","parent","findParentScrollable","scrollPosition","offsetDiff","top","height","getOffsetClipRect","viewportHeight","parentTop","parentHeight","offsetTop","el","overflowY","width","left","findPos","offsetLeft","offsetParent","onMounted","nextTick","onBeforeUnmount"],"mappings":"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"}
1
+ {"version":3,"file":"Textarea.js","sources":["../src/components/Textarea/Textarea.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n import { computed, nextTick, onBeforeUnmount, onMounted, ref, useAttrs, useCssModule, useSlots, watch } from 'vue';\n\n import { FieldProps } from '../Field/Field.types';\n import Field from '../Field/Field.vue';\n\n export interface TextareaResizeOptions {\n /**\n * It will automatically scroll the page down when it reaches the bottom of the viewport/element\n */\n forceBrowserScroll: boolean;\n }\n\n export interface TextAreaProps extends FieldProps {\n /**\n * Value for the textarea element.\n */\n modelValue?: string;\n\n /**\n * Deprecated. Use :model-value or v-model instead of :value.\n * @deprecated Use :model-value or v-model instead of :value.\n */\n value?: string | number | null;\n\n /**\n * Allow textarea to be resizable vertically.\n * Alternatively if you want to disable automatic scroll when resizing, you can set `{ forceBrowserScroll: false }`\n */\n resize?: boolean | TextareaResizeOptions;\n\n /**\n * Placeholder text for the textarea element.\n * **Note:** placeholders should be used to display examples; they should not be used as labels because they are not accessible as labels. If a real label cannot be used, use the `aria-label` attribute.\n */\n placeholder?: string;\n\n /**\n * Number of rows to display in the textarea.\n */\n rows?: number;\n\n /**\n * Maximum number of characters allowed in the textarea.\n */\n maxlength?: number;\n }\n\n defineOptions({\n name: 'll-textarea',\n });\n\n const attrs = useAttrs();\n const slots = useSlots();\n const classes = useCssModule();\n\n const props = withDefaults(defineProps<TextAreaProps>(), {\n modelValue: '',\n value: null,\n resize: false,\n maxlength: undefined,\n rows: undefined,\n placeholder: undefined,\n });\n\n const emits = defineEmits<{\n /**\n * Emitted when the model value changes.\n */\n (e: 'update:model-value', value: string): void;\n }>();\n\n const textareaRef = ref<HTMLTextAreaElement>();\n const observer = ref<ResizeObserver>();\n const isReadOnly = computed(() => props.isReadOnly || ('readonly' in attrs && attrs.readonly !== false));\n\n const inputAttrs = computed(() => {\n const allAttrs = { ...attrs };\n\n delete allAttrs['data-test'];\n delete allAttrs.class;\n\n return allAttrs;\n });\n\n watch(\n () => props.resize,\n (v) => {\n v ? setupResizeObserver() : observer.value?.disconnect();\n },\n );\n\n const onInput = (event: Event) => {\n emits('update:model-value', (event.target as HTMLTextAreaElement).value);\n };\n\n const setupResizeObserver = () => {\n if (observer.value || !textareaRef.value) {\n return;\n }\n\n // the ResizeObserver will be in charge to detect if page needs to scroll when resizing the component\n observer.value = new ResizeObserver(([entry]) => {\n const { target } = entry;\n const parent = findParentScrollable(textareaRef.value as HTMLTextAreaElement) || document.documentElement;\n\n const { scrollTop: scrollPosition } = parent;\n let offsetDiff = 0;\n\n // checks if the closest parent element scrollable is the document page\n if (parent === document.documentElement) {\n const { top, height } = getOffsetClipRect(target as HTMLElement);\n const { innerHeight: viewportHeight } = window;\n\n offsetDiff = Math.max(top + height - (viewportHeight + scrollPosition), 0);\n } else {\n const { top, height } = (target as HTMLElement).getBoundingClientRect();\n const { top: parentTop } = parent.getBoundingClientRect();\n const { offsetHeight: parentHeight } = parent;\n const offsetTop = top - parentTop;\n\n offsetDiff = Math.max(offsetTop + height - parentHeight, 0);\n }\n\n if (offsetDiff) {\n requestAnimationFrame(() => {\n parent.scrollTop = scrollPosition + offsetDiff;\n });\n }\n });\n\n observer.value.observe(textareaRef.value);\n };\n\n /**\n * Retrieve the closest parent that has a scroll. Defaults to the document page.\n */\n const findParentScrollable = (el: HTMLElement): HTMLElement | null => {\n const parent = el.parentElement as HTMLElement;\n if (!parent) {\n return null;\n }\n\n const { overflowY } = getComputedStyle(parent);\n if (overflowY !== 'visible') {\n return parent;\n }\n\n if (parent === document.body) {\n return document.documentElement;\n }\n\n return findParentScrollable(parent);\n };\n\n /**\n * Retrieve element absolute positioning relative to the page.\n */\n const getOffsetClipRect = (el: HTMLElement) => {\n const { offsetWidth: width, offsetHeight: height } = el;\n\n let left = 0;\n let top = 0;\n\n const findPos = function ({ offsetLeft, offsetTop, offsetParent }: HTMLElement) {\n left += offsetLeft;\n top += offsetTop;\n\n if (offsetParent) {\n findPos(offsetParent as HTMLElement);\n }\n };\n\n findPos(el);\n\n return {\n top,\n left,\n width,\n height,\n };\n };\n\n onMounted(async () => {\n if (props.value !== null) {\n throw new Error('ll-input: use :model-value or v-model instead of :value.');\n }\n\n if (attrs.onInput) {\n throw new Error('ll-input: use the @update:model-value event instead of @input');\n }\n\n if (\n (typeof props.resize === 'boolean' && props.resize) ||\n (props.resize as TextareaResizeOptions)?.forceBrowserScroll\n ) {\n await nextTick();\n setupResizeObserver();\n }\n });\n\n onBeforeUnmount(() => {\n observer.value?.disconnect();\n });\n</script>\n\n<template>\n <Field v-bind=\"props\" class=\"stash-textarea\" :class=\"[classes.root]\" data-test=\"stash-textarea\">\n <template #default=\"{ fieldId, hasError }\">\n <textarea\n :id=\"fieldId\"\n ref=\"textareaRef\"\n :class=\"[\n classes.textarea,\n 'tw-border tw-border-ice-500',\n {\n 'stash-textarea--error tw-border-red-500 tw-text-red-500': hasError,\n 'tw-text-ice-700 hover:tw-border-ice-500 focus:tw-border-blue-500 active:tw-border-blue-500':\n !hasError && !props.disabled,\n 'tw-resize-y': props.resize,\n 'tw-min-h-[100px]': !props.rows,\n 'tw-resize-none': !props.resize,\n },\n ]\"\n :maxlength=\"props.maxlength\"\n :value=\"props.modelValue\"\n data-test=\"stash-textarea|textarea\"\n :placeholder=\"props.placeholder\"\n v-bind=\"inputAttrs\"\n :disabled=\"props.disabled\"\n :readonly=\"isReadOnly\"\n :rows=\"props.rows\"\n @input=\"onInput\"\n ></textarea>\n </template>\n <template v-if=\"slots.hint\" #hint>\n <!-- @slot Hint content -->\n <slot name=\"hint\"></slot>\n </template>\n </Field>\n</template>\n\n<style module>\n .root {\n position: relative;\n width: 100%;\n }\n\n .textarea {\n background: var(--color-white);\n border-radius: theme('borderRadius.DEFAULT');\n display: block;\n outline: none;\n padding: theme('spacing[1.5]');\n width: 100%;\n\n &::placeholder {\n color: var(--color-ice-500);\n opacity: 1;\n }\n\n &[disabled] {\n background-color: var(--color-ice-100);\n border-color: var(--color-ice-500);\n color: var(--color-ice-500);\n pointer-events: none;\n }\n\n &[disabled]:active,\n &[disabled]:focus {\n box-shadow: none;\n }\n\n &[disabled]::placeholder {\n text-transform: none;\n color: var(--color-ice-500);\n }\n\n &[readonly] {\n border-color: transparent;\n background-color: transparent;\n padding-left: 0;\n padding-right: 0;\n min-height: unset;\n }\n }\n</style>\n"],"names":["attrs","useAttrs","slots","useSlots","classes","useCssModule","props","__props","emits","__emit","textareaRef","ref","observer","isReadOnly","computed","inputAttrs","allAttrs","watch","v","setupResizeObserver","_a","onInput","event","entry","target","parent","findParentScrollable","scrollPosition","offsetDiff","top","height","getOffsetClipRect","viewportHeight","parentTop","parentHeight","offsetTop","el","overflowY","width","left","findPos","offsetLeft","offsetParent","onMounted","nextTick","onBeforeUnmount"],"mappings":"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"}
@@ -36,6 +36,8 @@ declare const _default: __VLS_WithTemplateSlots<DefineComponent<ExtractPropTypes
36
36
  modelValue: string;
37
37
  value: null;
38
38
  resize: boolean;
39
+ maxlength: undefined;
40
+ rows: undefined;
39
41
  placeholder: undefined;
40
42
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
41
43
  "update:model-value": (value: string) => void;
@@ -43,6 +45,8 @@ placeholder: undefined;
43
45
  modelValue: string;
44
46
  value: null;
45
47
  resize: boolean;
48
+ maxlength: undefined;
49
+ rows: undefined;
46
50
  placeholder: undefined;
47
51
  }>>> & Readonly<{
48
52
  "onUpdate:model-value"?: ((value: string) => any) | undefined;
@@ -51,6 +55,8 @@ resize: boolean | TextareaResizeOptions;
51
55
  placeholder: string;
52
56
  modelValue: string;
53
57
  value: string | number | null;
58
+ maxlength: number;
59
+ rows: number;
54
60
  }, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>, {
55
61
  hint?(_: {}): any;
56
62
  }>;
@@ -133,6 +139,10 @@ export declare interface TextAreaProps extends FieldProps {
133
139
  * Number of rows to display in the textarea.
134
140
  */
135
141
  rows?: number;
142
+ /**
143
+ * Maximum number of characters allowed in the textarea.
144
+ */
145
+ maxlength?: number;
136
146
  }
137
147
 
138
148
  export declare interface TextareaResizeOptions {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leaflink/stash",
3
- "version": "50.8.1",
3
+ "version": "50.10.0",
4
4
  "description": "LeafLink's design system.",
5
5
  "homepage": "https://stash.leaflink.com",
6
6
  "main": "./dist/index.ts",