@leaflink/stash 50.0.7 → 50.1.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.
@@ -743,6 +743,10 @@ type: PropType<string>;
743
743
  id: {
744
744
  type: PropType<string>;
745
745
  };
746
+ trackBy: {
747
+ type: PropType<string>;
748
+ default: undefined;
749
+ };
746
750
  isRequired: {
747
751
  type: PropType<boolean>;
748
752
  };
@@ -771,6 +775,10 @@ placeholder: {
771
775
  type: PropType<string>;
772
776
  default: undefined;
773
777
  };
778
+ displayBy: {
779
+ type: PropType<string>;
780
+ default: undefined;
781
+ };
774
782
  options: {
775
783
  type: PropType<any[]>;
776
784
  default: () => never[];
@@ -817,7 +825,9 @@ type: "input" | "select";
817
825
  }) => void;
818
826
  }, PublicProps, {
819
827
  type: string;
828
+ trackBy: string;
820
829
  placeholder: string;
830
+ displayBy: string;
821
831
  options: any[];
822
832
  modelValue: {
823
833
  value: string;
@@ -848,6 +858,10 @@ type: PropType<string>;
848
858
  id: {
849
859
  type: PropType<string>;
850
860
  };
861
+ trackBy: {
862
+ type: PropType<string>;
863
+ default: undefined;
864
+ };
851
865
  isRequired: {
852
866
  type: PropType<boolean>;
853
867
  };
@@ -876,6 +890,10 @@ placeholder: {
876
890
  type: PropType<string>;
877
891
  default: undefined;
878
892
  };
893
+ displayBy: {
894
+ type: PropType<string>;
895
+ default: undefined;
896
+ };
879
897
  options: {
880
898
  type: PropType<any[]>;
881
899
  default: () => never[];
@@ -909,7 +927,9 @@ type: "input" | "select";
909
927
  }) => any) | undefined;
910
928
  }>, {}, {}, {}, {}, {
911
929
  type: string;
930
+ trackBy: string;
912
931
  placeholder: string;
932
+ displayBy: string;
913
933
  options: any[];
914
934
  modelValue: {
915
935
  value: string;
@@ -937,6 +957,10 @@ type: PropType<string>;
937
957
  id: {
938
958
  type: PropType<string>;
939
959
  };
960
+ trackBy: {
961
+ type: PropType<string>;
962
+ default: undefined;
963
+ };
940
964
  isRequired: {
941
965
  type: PropType<boolean>;
942
966
  };
@@ -965,6 +989,10 @@ placeholder: {
965
989
  type: PropType<string>;
966
990
  default: undefined;
967
991
  };
992
+ displayBy: {
993
+ type: PropType<string>;
994
+ default: undefined;
995
+ };
968
996
  options: {
969
997
  type: PropType<any[]>;
970
998
  default: () => never[];
@@ -1011,7 +1039,9 @@ type: "input" | "select";
1011
1039
  }) => void;
1012
1040
  }, string, {
1013
1041
  type: string;
1042
+ trackBy: string;
1014
1043
  placeholder: string;
1044
+ displayBy: string;
1015
1045
  options: any[];
1016
1046
  modelValue: {
1017
1047
  value: string;
package/dist/Image.js CHANGED
@@ -1,15 +1,15 @@
1
- import { defineComponent as W, inject as A, computed as a, useAttrs as M, openBlock as B, createElementBlock as k, mergeProps as C, unref as L } from "vue";
2
- import { IMAGE_PROVIDER_URLS as N, SCREEN_SIZES as y } from "./constants.js";
1
+ import { defineComponent as W, inject as C, computed as a, useAttrs as M, openBlock as B, createElementBlock as k, mergeProps as L, unref as $ } from "vue";
2
+ import { IMAGE_PROVIDER_URLS as N, SCREEN_SIZES as w } from "./constants.js";
3
3
  import q from "lodash-es/merge";
4
- const $ = {
4
+ const j = {
5
5
  xs: 160,
6
6
  sm: 338,
7
7
  md: 676,
8
8
  lg: 1352,
9
9
  xl: 2704
10
10
  };
11
- var w = /* @__PURE__ */ ((t) => (t.None = "none", t.Rounded = "rounded", t))(w || {}), z = /* @__PURE__ */ ((t) => (t.Cloudinary = "cloudinary", t.Static = "static", t))(z || {});
12
- function j(t) {
11
+ var z = /* @__PURE__ */ ((t) => (t.None = "none", t.Rounded = "rounded", t.Circle = "circle", t))(z || {}), b = /* @__PURE__ */ ((t) => (t.Cloudinary = "cloudinary", t.Static = "static", t))(b || {});
12
+ function P(t) {
13
13
  return (s) => t[s] || s;
14
14
  }
15
15
  function G({
@@ -18,16 +18,16 @@ function G({
18
18
  joinWith: i = "/",
19
19
  valueMap: e = {}
20
20
  } = {}) {
21
- const m = typeof s == "function" ? s : j(s || {});
21
+ const m = typeof s == "function" ? s : P(s || {});
22
22
  return Object.keys(e).forEach((c) => {
23
- typeof e[c] != "function" && (e[c] = j(e[c]));
24
- }), (c = {}) => Object.entries(c).map(([d, l]) => {
25
- const p = e[d], g = m(d);
26
- let v = l;
27
- return typeof p == "function" && (v = p(c[d])), t(g, v);
23
+ typeof e[c] != "function" && (e[c] = P(e[c]));
24
+ }), (c = {}) => Object.entries(c).map(([l, d]) => {
25
+ const p = e[l], g = m(l);
26
+ let v = d;
27
+ return typeof p == "function" && (v = p(c[l])), t(g, v);
28
28
  }).join(i);
29
29
  }
30
- const Q = N.CLOUDINARY, T = (t) => t.startsWith("#") ? t.replace("#", "rgb_") : t, P = G({
30
+ const Q = N.CLOUDINARY, T = (t) => t.startsWith("#") ? t.replace("#", "rgb_") : t, E = G({
31
31
  keyMap: {
32
32
  fit: "c",
33
33
  width: "w",
@@ -59,13 +59,13 @@ const Q = N.CLOUDINARY, T = (t) => t.startsWith("#") ? t.replace("#", "rgb_") :
59
59
  quality: "auto:best"
60
60
  };
61
61
  function F(t, s = {}) {
62
- const i = q(D, s), e = P(i);
62
+ const i = q(D, s), e = E(i);
63
63
  return `${Q}/${e}/${t}`;
64
64
  }
65
65
  const V = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
66
66
  __proto__: null,
67
67
  getImageUrl: F,
68
- operationsGenerator: P
68
+ operationsGenerator: E
69
69
  }, Symbol.toStringTag, { value: "Module" }));
70
70
  function H(t = "") {
71
71
  return t;
@@ -77,6 +77,7 @@ const Y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
77
77
  cloudinary: V,
78
78
  static: Y
79
79
  }, J = ["src"], et = /* @__PURE__ */ W({
80
+ inheritAttrs: !1,
80
81
  __name: "Image",
81
82
  props: {
82
83
  src: { default: "" },
@@ -88,11 +89,11 @@ const Y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
88
89
  },
89
90
  setup(t) {
90
91
  const s = {
91
- md: y.md,
92
- lg: y.lg
93
- }, i = A("stashOptions"), e = t, m = a(() => {
92
+ md: w.md,
93
+ lg: w.lg
94
+ }, i = C("stashOptions"), e = t, m = a(() => {
94
95
  const { src: r, ...n } = M();
95
- return n.sizes = v.value, n.srcset = E.value, n;
96
+ return n.sizes = v.value, n.srcset = I.value, n;
96
97
  }), c = a(() => {
97
98
  try {
98
99
  return new URL(e.src), !0;
@@ -101,22 +102,22 @@ const Y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
101
102
  }
102
103
  }), S = a(() => {
103
104
  var r;
104
- return e.provider || ((r = i == null ? void 0 : i.images) == null ? void 0 : r.provider) || z.Static;
105
- }), d = a(() => e.staticPath ?? (i == null ? void 0 : i.staticPath)), l = a(() => S.value === z.Static), p = a(() => Z[S.value]), g = a(() => l.value ? _() : _({ width: $.md })), v = a(() => e.sizes ? U() : e.sizes), E = a(() => e.sizes && !e.srcset && !l.value ? R() : e.srcset), I = a(() => e.sizes ? O(e.sizes) : []);
105
+ return e.provider || ((r = i == null ? void 0 : i.images) == null ? void 0 : r.provider) || b.Static;
106
+ }), l = a(() => e.staticPath ?? (i == null ? void 0 : i.staticPath)), d = a(() => S.value === b.Static), p = a(() => Z[S.value]), g = a(() => d.value ? _() : _({ width: j.md })), v = a(() => e.sizes ? O() : e.sizes), I = a(() => e.sizes && !e.srcset && !d.value ? R() : e.srcset), U = a(() => e.sizes ? x(e.sizes) : []);
106
107
  function _(r = {}) {
107
- if (l.value && c.value)
108
+ if (d.value && c.value)
108
109
  return e.src;
109
- const n = l.value && d.value ? `${d.value}/${e.src}` : e.src;
110
+ const n = d.value && l.value ? `${l.value}/${e.src}` : e.src;
110
111
  return p.value.getImageUrl(n, r);
111
112
  }
112
113
  function R() {
113
- return Object.values($).map((r) => `${_({ width: r })} ${r}w`).join(", ");
114
+ return Object.values(j).map((r) => `${_({ width: r })} ${r}w`).join(", ");
114
115
  }
115
- function U() {
116
+ function O() {
116
117
  var r;
117
- return (r = e.sizes) != null && r.includes("(") ? e.sizes : I.value.map((n) => `${n.mediaQuery ? n.mediaQuery + " " : ""}${n.size}`).join(", ");
118
+ return (r = e.sizes) != null && r.includes("(") ? e.sizes : U.value.map((n) => `${n.mediaQuery ? n.mediaQuery + " " : ""}${n.size}`).join(", ");
118
119
  }
119
- function O(r = "") {
120
+ function x(r = "") {
120
121
  const n = [], h = {
121
122
  default: "100vw"
122
123
  };
@@ -135,33 +136,34 @@ const Y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
135
136
  for (const f in h) {
136
137
  const u = parseInt(s[f] || 0);
137
138
  let o = String(h[f]);
138
- const b = o.endsWith("vw");
139
- if (!b && /^\d+$/.test(o) && (o = `${o}px`), !b && o.endsWith("%"))
139
+ const y = o.endsWith("vw");
140
+ if (!y && /^\d+$/.test(o) && (o = `${o}px`), !y && o.endsWith("%"))
140
141
  throw new Error("Image: `sizes` does not support percentage values");
141
- const x = {
142
+ const A = {
142
143
  mediaQuery: u ? `(min-width: ${u}px)` : "",
143
144
  screenMinWidth: u,
144
145
  size: o
145
146
  };
146
- n.push(x);
147
+ n.push(A);
147
148
  }
148
149
  return n.sort((f, u) => f.screenMinWidth > u.screenMinWidth ? -1 : 1), n;
149
150
  }
150
- return (r, n) => (B(), k("img", C({
151
+ return (r, n) => (B(), k("img", L({
151
152
  ref: "img",
152
153
  key: g.value,
153
154
  "data-test": "stash-image",
154
155
  class: ["stash-image", {
155
- "tw-rounded": e.radius === L(w).Rounded
156
+ "tw-rounded": e.radius === $(z).Rounded,
157
+ "tw-rounded-full": e.radius === $(z).Circle
156
158
  }],
157
159
  src: g.value
158
160
  }, m.value), null, 16, J));
159
161
  }
160
162
  });
161
163
  export {
162
- z as ImageProviders,
163
- w as ImageRadius,
164
- $ as Screens,
164
+ b as ImageProviders,
165
+ z as ImageRadius,
166
+ j as Screens,
165
167
  et as default
166
168
  };
167
169
  //# sourceMappingURL=Image.js.map
package/dist/Image.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Image.js","sources":["../src/components/Image/Image.types.ts","../src/components/Image/providers/utils.ts","../src/components/Image/providers/cloudinary.ts","../src/components/Image/providers/static.ts","../src/components/Image/providers/index.ts","../src/components/Image/Image.vue"],"sourcesContent":["// Sizes used to generate resized and optimized versions of an image.\n// Generated in `srcset`, and informed by `sizes`.\nexport const Screens = {\n xs: 160,\n sm: 338,\n md: 676,\n lg: 1352,\n xl: 2704,\n} as const;\n\nexport interface ImageSizeCondition {\n mediaQuery: string;\n screenMinWidth: number;\n size: string;\n}\n\nexport enum ImageRadius {\n None = 'none',\n Rounded = 'rounded',\n}\n\nexport type ImageRadii = `${ImageRadius}`;\n\nexport enum ImageProviders {\n Cloudinary = 'cloudinary',\n Static = 'static',\n}\n","export interface ImageModifiers {\n format?: string;\n height?: number;\n width?: number;\n [key: string]: any /* eslint-disable-line @typescript-eslint/no-explicit-any */;\n}\n\nexport type ParamFormatter = (key: string, value: string) => string;\n\nexport type ParamMapper = { [key: string]: string } | ((key: string) => string);\n\nexport interface ProviderUrlBuilder {\n keyMap?: ParamMapper;\n formatter?: ParamFormatter;\n joinWith?: string;\n valueMap?: {\n [key: string]: ParamMapper;\n };\n}\n\nfunction createMapper(map: ParamMapper) {\n return (key: string) => {\n return map[key] || key;\n };\n}\n\n/**\n * Builds the parameterized Cloudinary url\n */\nexport function buildProviderUrl({\n formatter = (key, value) => `${key}=${value}`,\n keyMap,\n joinWith = '/',\n valueMap = {},\n}: ProviderUrlBuilder = {}) {\n const keyMapper = typeof keyMap === 'function' ? keyMap : createMapper(keyMap || {});\n\n Object.keys(valueMap).forEach((valueKey) => {\n if (typeof valueMap[valueKey] !== 'function') {\n valueMap[valueKey] = createMapper(valueMap[valueKey]);\n }\n });\n\n return (modifiers: { [key: string]: string } = {}) => {\n const operations = Object.entries(modifiers).map(([key, value]) => {\n const mapper = valueMap[key];\n const newKey = keyMapper(key);\n let newVal = value;\n\n if (typeof mapper === 'function') {\n newVal = mapper(modifiers[key]);\n }\n\n return formatter(newKey, newVal);\n });\n\n return operations.join(joinWith);\n };\n}\n\n/**\n * Checks if a (sub)domain is included in a list of acceptable domains\n * @param str the (sub)domain to check\n * @param domains an array of valid domains\n */\nexport function isDomainValid(str = '', domains: string[] = []): boolean {\n const url = new URL(str);\n const host = url.host;\n\n return domains.some((domain) => {\n if (domain === host) {\n return true;\n }\n\n return domain.endsWith(`.${host}`);\n });\n}\n","import merge from 'lodash-es/merge';\n\nimport { IMAGE_PROVIDER_URLS } from '../../../constants';\nimport { buildProviderUrl, ImageModifiers } from './utils';\n\nconst BASE_URL = IMAGE_PROVIDER_URLS.CLOUDINARY;\n\nconst convertHextoRGBFormat = (value: string) => (value.startsWith('#') ? value.replace('#', 'rgb_') : value);\n\n/**\n * Parameters (option and value pairs) that can be used in the <transformations> segment of the Cloudinary transformation URL.\n * Options and their respective values are connected by an underscore (eg `w_250` for width of 250px.).\n * Multiple parameters are comma separated (eg. `w_250,h_250`).\n *\n * `keyMap` maps the option to its option prefix.\n * `valueMap` is used for grouping options using the same `keyMap` value under a 'category', allowing for easier usage and custom labelling in the component context.\n *\n * Transformation URL structure:\n * https://cloudinary.com/documentation/transformation_reference\n *\n * Transformation URL parameters (options and values):\n * https://cloudinary.com/documentation/image_transformations#transformation_url_syntax\n *\n */\nexport const operationsGenerator = buildProviderUrl({\n keyMap: {\n fit: 'c',\n width: 'w',\n height: 'h',\n format: 'f',\n quality: 'q',\n background: 'b',\n dpr: 'dpr',\n },\n valueMap: {\n fit: {\n fill: 'fill',\n inside: 'pad',\n outside: 'lpad',\n cover: 'fit',\n contain: 'scale',\n },\n format: {\n jpeg: 'jpg',\n },\n background(value: string) {\n return convertHextoRGBFormat(value);\n },\n },\n joinWith: ',',\n formatter: (key, value) => `${key}_${value}`,\n});\n\n// Note: Not configurable via Image props (for now).\nconst defaultModifiers = {\n format: 'auto',\n quality: 'auto:best',\n};\n\nexport function getImageUrl(src: string, modifiers: Partial<ImageModifiers> = {}): string {\n const mergeModifiers = merge(defaultModifiers, modifiers);\n const operations = operationsGenerator(mergeModifiers);\n\n return `${BASE_URL}/${operations}/${src}`;\n}\n","export function getImageUrl(src = ''): string {\n return src;\n}\n","import * as cloudinary from './cloudinary';\nimport * as staticProvider from './static';\n\nexport default {\n cloudinary,\n static: staticProvider,\n};\n","<script lang=\"ts\">\n export * from './Image.types';\n</script>\n\n<script setup lang=\"ts\">\n import { computed, inject, useAttrs } from 'vue';\n\n import { StashImageProviders, StashProvideState } from '../../../types/misc';\n import { SCREEN_SIZES } from '../../constants';\n import { ImageProviders, ImageRadii, ImageRadius, ImageSizeCondition, Screens } from './Image.types';\n import providers from './providers';\n import { ImageModifiers } from './providers/utils';\n\n export interface ImageProps {\n /**\n * The path to the image you want to embed.\n */\n src: string;\n\n /**\n * Native srcset attribute.\n * One or more strings separated by commas, indicating possible image sources\n * Can only be used with provider=static, otherwise it's ignored and auto-generated with `sizes` usage\n */\n srcset?: string;\n\n /**\n * For specifying responsive sizes\n */\n sizes?: string;\n\n /**\n * Where the image is served from.\n * If not provided, the provider will inherit from the Stash config `stashOptions.images.provider` (default: `static`).\n * - `static` for relative or absolute paths\n * - `cloudinary` for images served via Cloudinary\n */\n provider?: StashImageProviders;\n\n /**\n * For applying border radius\n */\n radius?: ImageRadii;\n\n /**\n * A custom static path the image src will be appended onto when provider=static.\n * Can be used to override the library-level default.\n */\n staticPath?: string;\n\n /**\n * TODO - https://leaflink.atlassian.net/browse/GRO-204\n * A custom function used to resolve a URL string for the image\n */\n // loader?: () => string;\n }\n\n const BREAKPOINTS = {\n md: SCREEN_SIZES.md,\n lg: SCREEN_SIZES.lg,\n };\n const stashOptions = inject<StashProvideState>('stashOptions');\n const props = withDefaults(defineProps<ImageProps>(), {\n src: '',\n srcset: undefined,\n sizes: undefined,\n staticPath: undefined,\n provider: undefined,\n radius: 'none',\n // loader: undefined, // TODO - https://leaflink.atlassian.net/browse/GRO-204\n });\n\n const attrs = computed(() => {\n const { src, ...attrs } = useAttrs();\n\n attrs.sizes = imgSizes.value;\n attrs.srcset = imgSrcset.value;\n\n return attrs;\n });\n\n const isAbsoluteUrl = computed(() => {\n // return true if not an absolute url\n try {\n new URL(props.src);\n return true;\n } catch (e) {\n return false;\n }\n });\n\n const computedProvider = computed(() => props.provider || stashOptions?.images?.provider || ImageProviders.Static);\n\n const computedStaticPath = computed(() => props.staticPath ?? stashOptions?.staticPath);\n\n const isStatic = computed(() => computedProvider.value === ImageProviders.Static);\n\n const imgProvider = computed(() => providers[computedProvider.value]);\n\n const imgSrc = computed(() => (isStatic.value ? getProviderImage() : getProviderImage({ width: Screens.md })));\n\n const imgSizes = computed(() => (props.sizes ? getSizes() : props.sizes));\n\n const imgSrcset = computed(() => (props.sizes && !props.srcset && !isStatic.value ? getSources() : props.srcset));\n\n const parsedSizes = computed(() => {\n return props.sizes ? parseSizes(props.sizes) : [];\n });\n\n function getProviderImage(modifiers: ImageModifiers = {}) {\n if (isStatic.value && isAbsoluteUrl.value) {\n return props.src;\n }\n\n const src = isStatic.value && computedStaticPath.value ? `${computedStaticPath.value}/${props.src}` : props.src;\n\n return imgProvider.value.getImageUrl(src, modifiers);\n }\n\n function getSources() {\n return Object.values(Screens)\n .map((width) => {\n const src = getProviderImage({ width });\n\n return `${src} ${width}w`;\n })\n .join(', ');\n }\n\n function getSizes() {\n // return if using native media conditions\n if (props.sizes?.includes('(')) {\n return props.sizes;\n }\n\n return parsedSizes.value.map((v) => `${v.mediaQuery ? v.mediaQuery + ' ' : ''}${v.size}`).join(', ');\n }\n\n function parseSizes(providedSizes = '') {\n const conditions: ImageSizeCondition[] = [];\n const sizes = {\n default: '100vw',\n };\n\n // parse sizes and convert to object\n if (typeof providedSizes === 'string') {\n const definitions = providedSizes.split(/[\\s]+/).filter((size) => size);\n\n for (const entry of definitions) {\n const size = entry.split(':');\n\n if (size.length !== 2) {\n sizes['default'] = size[0].trim();\n continue;\n }\n\n sizes[size[0].trim()] = size[1].trim();\n }\n } else {\n throw new Error('`sizes` needs to be a string');\n }\n\n for (const key in sizes) {\n const screenMinWidth = parseInt(BREAKPOINTS[key] || 0);\n let size = String(sizes[key]);\n const isFluidSize = size.endsWith('vw');\n\n // convert integer to pixels\n if (!isFluidSize && /^\\d+$/.test(size)) {\n size = `${size}px`;\n }\n\n if (!isFluidSize && size.endsWith('%')) {\n throw new Error('Image: `sizes` does not support percentage values');\n }\n\n const condition = {\n mediaQuery: screenMinWidth ? `(min-width: ${screenMinWidth}px)` : '',\n screenMinWidth,\n size,\n };\n\n conditions.push(condition);\n }\n\n conditions.sort((v1, v2) => (v1.screenMinWidth > v2.screenMinWidth ? -1 : 1));\n\n return conditions;\n }\n</script>\n\n<template>\n <img\n ref=\"img\"\n :key=\"imgSrc\"\n data-test=\"stash-image\"\n class=\"stash-image\"\n :class=\"{\n 'tw-rounded': props.radius === ImageRadius.Rounded,\n }\"\n :src=\"imgSrc\"\n v-bind=\"attrs\"\n />\n</template>\n"],"names":["Screens","ImageRadius","ImageProviders","createMapper","map","key","buildProviderUrl","formatter","value","keyMap","joinWith","valueMap","keyMapper","valueKey","modifiers","mapper","newKey","newVal","BASE_URL","IMAGE_PROVIDER_URLS","convertHextoRGBFormat","operationsGenerator","defaultModifiers","getImageUrl","src","mergeModifiers","merge","operations","providers","cloudinary","staticProvider","BREAKPOINTS","SCREEN_SIZES","stashOptions","inject","props","__props","attrs","computed","useAttrs","imgSizes","imgSrcset","isAbsoluteUrl","computedProvider","_a","computedStaticPath","isStatic","imgProvider","imgSrc","getProviderImage","getSizes","getSources","parsedSizes","parseSizes","width","v","providedSizes","conditions","sizes","definitions","size","entry","screenMinWidth","isFluidSize","condition","v1","v2"],"mappings":"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"}
1
+ {"version":3,"file":"Image.js","sources":["../src/components/Image/Image.types.ts","../src/components/Image/providers/utils.ts","../src/components/Image/providers/cloudinary.ts","../src/components/Image/providers/static.ts","../src/components/Image/providers/index.ts","../src/components/Image/Image.vue"],"sourcesContent":["// Sizes used to generate resized and optimized versions of an image.\n// Generated in `srcset`, and informed by `sizes`.\nexport const Screens = {\n xs: 160,\n sm: 338,\n md: 676,\n lg: 1352,\n xl: 2704,\n} as const;\n\nexport interface ImageSizeCondition {\n mediaQuery: string;\n screenMinWidth: number;\n size: string;\n}\n\nexport enum ImageRadius {\n None = 'none',\n Rounded = 'rounded',\n Circle = 'circle',\n}\n\nexport type ImageRadii = `${ImageRadius}`;\n\nexport enum ImageProviders {\n Cloudinary = 'cloudinary',\n Static = 'static',\n}\n","export interface ImageModifiers {\n format?: string;\n height?: number;\n width?: number;\n [key: string]: any /* eslint-disable-line @typescript-eslint/no-explicit-any */;\n}\n\nexport type ParamFormatter = (key: string, value: string) => string;\n\nexport type ParamMapper = { [key: string]: string } | ((key: string) => string);\n\nexport interface ProviderUrlBuilder {\n keyMap?: ParamMapper;\n formatter?: ParamFormatter;\n joinWith?: string;\n valueMap?: {\n [key: string]: ParamMapper;\n };\n}\n\nfunction createMapper(map: ParamMapper) {\n return (key: string) => {\n return map[key] || key;\n };\n}\n\n/**\n * Builds the parameterized Cloudinary url\n */\nexport function buildProviderUrl({\n formatter = (key, value) => `${key}=${value}`,\n keyMap,\n joinWith = '/',\n valueMap = {},\n}: ProviderUrlBuilder = {}) {\n const keyMapper = typeof keyMap === 'function' ? keyMap : createMapper(keyMap || {});\n\n Object.keys(valueMap).forEach((valueKey) => {\n if (typeof valueMap[valueKey] !== 'function') {\n valueMap[valueKey] = createMapper(valueMap[valueKey]);\n }\n });\n\n return (modifiers: { [key: string]: string } = {}) => {\n const operations = Object.entries(modifiers).map(([key, value]) => {\n const mapper = valueMap[key];\n const newKey = keyMapper(key);\n let newVal = value;\n\n if (typeof mapper === 'function') {\n newVal = mapper(modifiers[key]);\n }\n\n return formatter(newKey, newVal);\n });\n\n return operations.join(joinWith);\n };\n}\n\n/**\n * Checks if a (sub)domain is included in a list of acceptable domains\n * @param str the (sub)domain to check\n * @param domains an array of valid domains\n */\nexport function isDomainValid(str = '', domains: string[] = []): boolean {\n const url = new URL(str);\n const host = url.host;\n\n return domains.some((domain) => {\n if (domain === host) {\n return true;\n }\n\n return domain.endsWith(`.${host}`);\n });\n}\n","import merge from 'lodash-es/merge';\n\nimport { IMAGE_PROVIDER_URLS } from '../../../constants';\nimport { buildProviderUrl, ImageModifiers } from './utils';\n\nconst BASE_URL = IMAGE_PROVIDER_URLS.CLOUDINARY;\n\nconst convertHextoRGBFormat = (value: string) => (value.startsWith('#') ? value.replace('#', 'rgb_') : value);\n\n/**\n * Parameters (option and value pairs) that can be used in the <transformations> segment of the Cloudinary transformation URL.\n * Options and their respective values are connected by an underscore (eg `w_250` for width of 250px.).\n * Multiple parameters are comma separated (eg. `w_250,h_250`).\n *\n * `keyMap` maps the option to its option prefix.\n * `valueMap` is used for grouping options using the same `keyMap` value under a 'category', allowing for easier usage and custom labelling in the component context.\n *\n * Transformation URL structure:\n * https://cloudinary.com/documentation/transformation_reference\n *\n * Transformation URL parameters (options and values):\n * https://cloudinary.com/documentation/image_transformations#transformation_url_syntax\n *\n */\nexport const operationsGenerator = buildProviderUrl({\n keyMap: {\n fit: 'c',\n width: 'w',\n height: 'h',\n format: 'f',\n quality: 'q',\n background: 'b',\n dpr: 'dpr',\n },\n valueMap: {\n fit: {\n fill: 'fill',\n inside: 'pad',\n outside: 'lpad',\n cover: 'fit',\n contain: 'scale',\n },\n format: {\n jpeg: 'jpg',\n },\n background(value: string) {\n return convertHextoRGBFormat(value);\n },\n },\n joinWith: ',',\n formatter: (key, value) => `${key}_${value}`,\n});\n\n// Note: Not configurable via Image props (for now).\nconst defaultModifiers = {\n format: 'auto',\n quality: 'auto:best',\n};\n\nexport function getImageUrl(src: string, modifiers: Partial<ImageModifiers> = {}): string {\n const mergeModifiers = merge(defaultModifiers, modifiers);\n const operations = operationsGenerator(mergeModifiers);\n\n return `${BASE_URL}/${operations}/${src}`;\n}\n","export function getImageUrl(src = ''): string {\n return src;\n}\n","import * as cloudinary from './cloudinary';\nimport * as staticProvider from './static';\n\nexport default {\n cloudinary,\n static: staticProvider,\n};\n","<script lang=\"ts\">\n export * from './Image.types';\n</script>\n\n<script setup lang=\"ts\">\n import { computed, inject, useAttrs } from 'vue';\n\n import { StashImageProviders, StashProvideState } from '../../../types/misc';\n import { SCREEN_SIZES } from '../../constants';\n import { ImageProviders, ImageRadii, ImageRadius, ImageSizeCondition, Screens } from './Image.types';\n import providers from './providers';\n import { ImageModifiers } from './providers/utils';\n\n export interface ImageProps {\n /**\n * The path to the image you want to embed.\n */\n src: string;\n\n /**\n * Native srcset attribute.\n * One or more strings separated by commas, indicating possible image sources\n * Can only be used with provider=static, otherwise it's ignored and auto-generated with `sizes` usage\n */\n srcset?: string;\n\n /**\n * For specifying responsive sizes\n */\n sizes?: string;\n\n /**\n * Where the image is served from.\n * If not provided, the provider will inherit from the Stash config `stashOptions.images.provider` (default: `static`).\n * - `static` for relative or absolute paths\n * - `cloudinary` for images served via Cloudinary\n */\n provider?: StashImageProviders;\n\n /**\n * For applying border radius\n */\n radius?: ImageRadii;\n\n /**\n * A custom static path the image src will be appended onto when provider=static.\n * Can be used to override the library-level default.\n */\n staticPath?: string;\n\n /**\n * TODO - https://leaflink.atlassian.net/browse/GRO-204\n * A custom function used to resolve a URL string for the image\n */\n // loader?: () => string;\n }\n\n defineOptions({\n inheritAttrs: false,\n });\n\n const BREAKPOINTS = {\n md: SCREEN_SIZES.md,\n lg: SCREEN_SIZES.lg,\n };\n const stashOptions = inject<StashProvideState>('stashOptions');\n const props = withDefaults(defineProps<ImageProps>(), {\n src: '',\n srcset: undefined,\n sizes: undefined,\n staticPath: undefined,\n provider: undefined,\n radius: 'none',\n // loader: undefined, // TODO - https://leaflink.atlassian.net/browse/GRO-204\n });\n\n const attrs = computed(() => {\n const { src, ...attrs } = useAttrs();\n\n attrs.sizes = imgSizes.value;\n attrs.srcset = imgSrcset.value;\n\n return attrs;\n });\n\n const isAbsoluteUrl = computed(() => {\n // return true if not an absolute url\n try {\n new URL(props.src);\n return true;\n } catch (e) {\n return false;\n }\n });\n\n const computedProvider = computed(() => props.provider || stashOptions?.images?.provider || ImageProviders.Static);\n\n const computedStaticPath = computed(() => props.staticPath ?? stashOptions?.staticPath);\n\n const isStatic = computed(() => computedProvider.value === ImageProviders.Static);\n\n const imgProvider = computed(() => providers[computedProvider.value]);\n\n const imgSrc = computed(() => (isStatic.value ? getProviderImage() : getProviderImage({ width: Screens.md })));\n\n const imgSizes = computed(() => (props.sizes ? getSizes() : props.sizes));\n\n const imgSrcset = computed(() => (props.sizes && !props.srcset && !isStatic.value ? getSources() : props.srcset));\n\n const parsedSizes = computed(() => {\n return props.sizes ? parseSizes(props.sizes) : [];\n });\n\n function getProviderImage(modifiers: ImageModifiers = {}) {\n if (isStatic.value && isAbsoluteUrl.value) {\n return props.src;\n }\n\n const src = isStatic.value && computedStaticPath.value ? `${computedStaticPath.value}/${props.src}` : props.src;\n\n return imgProvider.value.getImageUrl(src, modifiers);\n }\n\n function getSources() {\n return Object.values(Screens)\n .map((width) => {\n const src = getProviderImage({ width });\n\n return `${src} ${width}w`;\n })\n .join(', ');\n }\n\n function getSizes() {\n // return if using native media conditions\n if (props.sizes?.includes('(')) {\n return props.sizes;\n }\n\n return parsedSizes.value.map((v) => `${v.mediaQuery ? v.mediaQuery + ' ' : ''}${v.size}`).join(', ');\n }\n\n function parseSizes(providedSizes = '') {\n const conditions: ImageSizeCondition[] = [];\n const sizes = {\n default: '100vw',\n };\n\n // parse sizes and convert to object\n if (typeof providedSizes === 'string') {\n const definitions = providedSizes.split(/[\\s]+/).filter((size) => size);\n\n for (const entry of definitions) {\n const size = entry.split(':');\n\n if (size.length !== 2) {\n sizes['default'] = size[0].trim();\n continue;\n }\n\n sizes[size[0].trim()] = size[1].trim();\n }\n } else {\n throw new Error('`sizes` needs to be a string');\n }\n\n for (const key in sizes) {\n const screenMinWidth = parseInt(BREAKPOINTS[key] || 0);\n let size = String(sizes[key]);\n const isFluidSize = size.endsWith('vw');\n\n // convert integer to pixels\n if (!isFluidSize && /^\\d+$/.test(size)) {\n size = `${size}px`;\n }\n\n if (!isFluidSize && size.endsWith('%')) {\n throw new Error('Image: `sizes` does not support percentage values');\n }\n\n const condition = {\n mediaQuery: screenMinWidth ? `(min-width: ${screenMinWidth}px)` : '',\n screenMinWidth,\n size,\n };\n\n conditions.push(condition);\n }\n\n conditions.sort((v1, v2) => (v1.screenMinWidth > v2.screenMinWidth ? -1 : 1));\n\n return conditions;\n }\n</script>\n\n<template>\n <img\n ref=\"img\"\n :key=\"imgSrc\"\n data-test=\"stash-image\"\n class=\"stash-image\"\n :class=\"{\n 'tw-rounded': props.radius === ImageRadius.Rounded,\n 'tw-rounded-full': props.radius === ImageRadius.Circle,\n }\"\n :src=\"imgSrc\"\n v-bind=\"attrs\"\n />\n</template>\n"],"names":["Screens","ImageRadius","ImageProviders","createMapper","map","key","buildProviderUrl","formatter","value","keyMap","joinWith","valueMap","keyMapper","valueKey","modifiers","mapper","newKey","newVal","BASE_URL","IMAGE_PROVIDER_URLS","convertHextoRGBFormat","operationsGenerator","defaultModifiers","getImageUrl","src","mergeModifiers","merge","operations","providers","cloudinary","staticProvider","BREAKPOINTS","SCREEN_SIZES","stashOptions","inject","props","__props","attrs","computed","useAttrs","imgSizes","imgSrcset","isAbsoluteUrl","computedProvider","_a","computedStaticPath","isStatic","imgProvider","imgSrc","getProviderImage","getSizes","getSources","parsedSizes","parseSizes","width","v","providedSizes","conditions","sizes","definitions","size","entry","screenMinWidth","isFluidSize","condition","v1","v2"],"mappings":"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"}
@@ -43,7 +43,7 @@ radius: string;
43
43
  }>>> & Readonly<{}>, {
44
44
  staticPath: string;
45
45
  src: string;
46
- radius: "none" | "rounded";
46
+ radius: "circle" | "none" | "rounded";
47
47
  srcset: string;
48
48
  sizes: string;
49
49
  provider: "static" | "cloudinary";
@@ -92,7 +92,8 @@ export declare type ImageRadii = `${ImageRadius}`;
92
92
 
93
93
  export declare enum ImageRadius {
94
94
  None = "none",
95
- Rounded = "rounded"
95
+ Rounded = "rounded",
96
+ Circle = "circle"
96
97
  }
97
98
 
98
99
  export declare interface ImageSizeCondition {
@@ -1,12 +1,12 @@
1
- import { defineComponent as E, useAttrs as T, useSlots as $, useCssModule as D, ref as r, computed as M, watchEffect as R, watch as v, openBlock as c, createBlock as z, mergeProps as h, createSlots as A, withCtx as f, createElementBlock as y, createElementVNode as F, toDisplayString as _, normalizeClass as w, unref as i, createVNode as b, renderSlot as N } from "vue";
2
- import U from "./Input.js";
3
- import q from "./Select.js";
4
- import { _ as L } from "./Field.vue_vue_type_script_setup_true_lang-DEizIcDo.js";
5
- import { _ as P } from "./_plugin-vue_export-helper-CHgC5LLL.js";
6
- const j = {
1
+ import { defineComponent as S, useAttrs as O, useSlots as E, useCssModule as T, ref as p, watchEffect as $, watch as h, openBlock as d, createBlock as D, mergeProps as M, createSlots as R, withCtx as f, createElementBlock as y, createElementVNode as z, toDisplayString as _, normalizeClass as r, unref as s, createVNode as b, renderSlot as F } from "vue";
2
+ import N from "./Input.js";
3
+ import U from "./Select.js";
4
+ import { _ as q } from "./Field.vue_vue_type_script_setup_true_lang-DEizIcDo.js";
5
+ import { _ as A } from "./_plugin-vue_export-helper-CHgC5LLL.js";
6
+ const L = {
7
7
  key: 0,
8
8
  class: "tw-flex tw-h-input tw-items-center tw-text-sm"
9
- }, G = ["id", "aria-labelledby"], H = /* @__PURE__ */ E({
9
+ }, P = ["id", "aria-labelledby"], j = /* @__PURE__ */ S({
10
10
  name: "ll-input-options",
11
11
  __name: "InputOptions",
12
12
  props: {
@@ -15,136 +15,137 @@ const j = {
15
15
  noTruncate: { type: Boolean, default: !1 },
16
16
  options: { default: () => [] },
17
17
  placeholder: { default: void 0 },
18
- disabled: { type: Boolean },
19
- isReadOnly: { type: Boolean },
18
+ displayBy: { default: void 0 },
19
+ trackBy: { default: void 0 },
20
20
  addBottomSpace: { type: Boolean },
21
21
  errorText: {},
22
22
  hintText: {},
23
23
  id: {},
24
24
  errorId: {},
25
+ isReadOnly: { type: Boolean },
25
26
  isRequired: { type: Boolean },
26
27
  label: {},
27
28
  showOptionalInLabel: { type: Boolean },
28
29
  fieldset: { type: Boolean },
29
- isDisabled: { type: Boolean }
30
+ isDisabled: { type: Boolean },
31
+ disabled: { type: Boolean }
30
32
  },
31
33
  emits: ["update:model-value", "change"],
32
- setup(g, { emit: B }) {
33
- const e = g, n = B, u = T(), V = $(), p = D(), o = r(), d = r(!1), t = r(), C = M(() => {
34
- const { disabled: l, displayBy: a, trackBy: s } = u;
35
- return { disabled: l, displayBy: a, trackBy: s };
36
- });
37
- function x(l) {
38
- o.value = String(l), n("update:model-value", {
39
- value: o.value,
34
+ setup(w, { emit: g }) {
35
+ const e = w, o = g, c = O(), B = E(), i = T(), l = p(), u = p(!1), t = p();
36
+ function V(a) {
37
+ l.value = String(a), o("update:model-value", {
38
+ value: l.value,
40
39
  option: t.value,
41
40
  isValueChange: !0,
42
41
  type: "input"
43
42
  });
44
43
  }
45
- function I() {
46
- n("change", {
47
- value: o.value,
44
+ function k() {
45
+ o("change", {
46
+ value: l.value,
48
47
  option: t.value,
49
48
  isValueChange: !0,
50
49
  type: "input"
51
50
  });
52
51
  }
53
- function k(l) {
54
- t.value = l, n("change", {
55
- value: o.value,
52
+ function C(a) {
53
+ t.value = a, o("change", {
54
+ value: l.value,
56
55
  option: t.value,
57
56
  isValueChange: !1,
58
57
  type: "select"
59
- }), n("update:model-value", {
60
- value: o.value,
58
+ }), o("update:model-value", {
59
+ value: l.value,
61
60
  option: t.value,
62
61
  isValueChange: !1,
63
62
  type: "select"
64
63
  });
65
64
  }
66
- if (R(() => {
65
+ if ($(() => {
67
66
  t.value || (t.value = e.options[0]);
68
- }), v(
67
+ }), h(
69
68
  () => e.modelValue.value,
70
69
  () => {
71
- o.value = e.modelValue.value;
70
+ l.value = e.modelValue.value;
72
71
  },
73
72
  { immediate: !0 }
74
- ), v(
73
+ ), h(
75
74
  () => e.modelValue.option,
76
75
  () => {
77
76
  t.value = e.modelValue.option;
78
77
  },
79
78
  { immediate: !0 }
80
- ), u.value)
79
+ ), c.value)
81
80
  throw new Error("ll-input-options: use :model-value or v-model instead of :value.");
82
- if (u.onInput)
81
+ if (c.onInput)
83
82
  throw new Error("ll-input-options: use the @update:model-value event instead of @input");
84
- return (l, a) => (c(), z(L, h(e, {
83
+ return (a, n) => (d(), D(q, M(e, {
85
84
  class: "stash-input-options",
86
85
  "data-test": "stash-input-options"
87
- }), A({
88
- default: f(({ fieldId: s, labelId: S }) => {
89
- var m;
86
+ }), R({
87
+ default: f(({ fieldId: m, labelId: x }) => {
88
+ var v;
90
89
  return [
91
- e.isReadOnly ? (c(), y("div", j, [
92
- F("span", {
93
- id: s,
94
- "aria-labelledby": S,
90
+ e.isReadOnly ? (d(), y("div", L, [
91
+ z("span", {
92
+ id: m,
93
+ "aria-labelledby": x,
95
94
  class: "tw-h-min"
96
- }, _(o.value || 0) + " " + _((m = t.value) == null ? void 0 : m.name), 9, G)
97
- ])) : (c(), y("div", {
95
+ }, _(l.value || 0) + " " + _((v = t.value) == null ? void 0 : v.name), 9, P)
96
+ ])) : (d(), y("div", {
98
97
  key: 1,
99
- class: w(["tw-flex", { [i(p)["has-error"]]: !!e.errorText }])
98
+ class: r(["tw-flex", { [s(i)["has-error"]]: !!e.errorText }])
100
99
  }, [
101
- b(U, {
102
- id: s,
103
- class: w(["stash-input-options__input -tw-mr-[1px] tw-inline-block tw-flex-1", [i(p).input, { "tw-z-control": d.value }]]),
100
+ b(N, {
101
+ id: m,
102
+ class: r(["stash-input-options__input -tw-mr-[1px] tw-inline-block tw-flex-1", [s(i).input, { "tw-z-control": u.value }]]),
104
103
  "data-test": "stash-input-options|input",
105
104
  type: e.type,
106
- "model-value": o.value,
105
+ "model-value": l.value,
107
106
  disabled: e.isDisabled || e.disabled,
108
107
  placeholder: e.placeholder,
109
- onChange: I,
110
- "onUpdate:modelValue": x,
111
- onBlur: a[0] || (a[0] = (O) => d.value = !1),
112
- onFocus: a[1] || (a[1] = (O) => d.value = !0)
108
+ onChange: k,
109
+ "onUpdate:modelValue": V,
110
+ onBlur: n[0] || (n[0] = (I) => u.value = !1),
111
+ onFocus: n[1] || (n[1] = (I) => u.value = !0)
113
112
  }, null, 8, ["id", "class", "type", "model-value", "disabled", "placeholder"]),
114
- b(q, h(C.value, {
113
+ b(U, {
115
114
  single: "",
116
115
  "hide-search": "",
117
116
  "prevent-empty": "",
118
- class: ["stash-input-options__select tw-min-w-20", i(p).select],
117
+ class: r(["stash-input-options__select tw-min-w-20", s(i).select]),
119
118
  "data-test": "stash-input-options|select",
120
- "no-truncate": l.noTruncate,
121
- options: l.options,
119
+ "no-truncate": a.noTruncate,
120
+ options: a.options,
122
121
  "model-value": t.value,
122
+ "display-by": e.displayBy,
123
+ "track-by": e.trackBy,
123
124
  disabled: e.isDisabled || e.disabled,
124
- "onUpdate:modelValue": k
125
- }), null, 16, ["class", "no-truncate", "options", "model-value", "disabled"])
125
+ "onUpdate:modelValue": C
126
+ }, null, 8, ["class", "no-truncate", "options", "model-value", "display-by", "track-by", "disabled"])
126
127
  ], 2))
127
128
  ];
128
129
  }),
129
130
  _: 2
130
131
  }, [
131
- i(V).hint ? {
132
+ s(B).hint ? {
132
133
  name: "hint",
133
134
  fn: f(() => [
134
- N(l.$slots, "hint")
135
+ F(a.$slots, "hint")
135
136
  ]),
136
137
  key: "0"
137
138
  } : void 0
138
139
  ]), 1040));
139
140
  }
140
- }), J = "_input_gn7he_2", K = "_select_gn7he_7", Q = {
141
- input: J,
142
- select: K,
141
+ }), G = "_input_gn7he_2", H = "_select_gn7he_7", J = {
142
+ input: G,
143
+ select: H,
143
144
  "has-error": "_has-error_gn7he_16"
144
- }, W = {
145
- $style: Q
146
- }, le = /* @__PURE__ */ P(H, [["__cssModules", W]]);
145
+ }, K = {
146
+ $style: J
147
+ }, ee = /* @__PURE__ */ A(j, [["__cssModules", K]]);
147
148
  export {
148
- le as default
149
+ ee as default
149
150
  };
150
151
  //# sourceMappingURL=InputOptions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InputOptions.js","sources":["../src/components/InputOptions/InputOptions.vue"],"sourcesContent":["<script lang=\"ts\">\n import Field, { type FieldProps } from '../Field/Field.vue';\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n type Option = any;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n type SelectedOption = any;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n export interface InputOptionsProps extends FieldProps {\n /**\n * The current value inclusive of the input & select\n */\n modelValue?: { value: string; option?: SelectedOption };\n\n /**\n * Input type\n */\n type?: string extends 'button' | 'checkbox' | 'radio' | 'submit' ? never : string;\n\n /**\n * Prevents the Selected Option from being truncated, if true\n */\n noTruncate?: boolean;\n\n /**\n * Options for the select\n */\n options?: Option[];\n\n /**\n * Placeholder text for the input\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 * Indicates whether the inputOptions is disabled.\n */\n disabled?: boolean;\n\n /**\n * Indicates whether the inputOptions is read-only.\n */\n isReadOnly?: boolean;\n }\n</script>\n\n<script lang=\"ts\" setup>\n import { computed, ref, useAttrs, useCssModule, useSlots, watch, watchEffect } from 'vue';\n\n import Input from '../Input/Input.vue';\n import Select from '../Select/Select.vue';\n\n defineOptions({\n name: 'll-input-options',\n });\n\n const props = withDefaults(defineProps<InputOptionsProps>(), {\n modelValue: () => ({ value: '', option: undefined }),\n noTruncate: false,\n options: () => [],\n type: 'text',\n placeholder: undefined,\n });\n\n const emit = defineEmits<{\n /**\n * Emitted when the model value changes\n */\n (\n e: 'update:model-value',\n v: { value?: string; option?: SelectedOption; isValueChange: boolean; type: 'input' | 'select' },\n ): void;\n /**\n * Emitted when either the input or select changes\n */\n (\n e: 'change',\n v: { value?: string; option?: SelectedOption; isValueChange: boolean; type: 'input' | 'select' },\n ): void;\n }>();\n\n const attrs = useAttrs();\n const slots = useSlots();\n const classes = useCssModule();\n const internalInput = ref<string>();\n const isInputFocused = ref(false);\n const selectedOption = ref<Option | undefined>();\n\n const selectAttrs = computed(() => {\n const { disabled, displayBy, trackBy } = attrs;\n\n return { disabled, displayBy, trackBy } as { disabled: boolean; displayBy: string; trackBy: string };\n });\n\n // Input value changed\n function handleInput(val?: string | number) {\n internalInput.value = String(val);\n\n emit('update:model-value', {\n value: internalInput.value,\n option: selectedOption.value,\n isValueChange: true,\n type: 'input',\n });\n }\n\n // Input blurred\n function handleInputChange() {\n emit('change', {\n value: internalInput.value,\n option: selectedOption.value,\n isValueChange: true,\n type: 'input',\n });\n }\n\n function handleSelectChange(val?: Option) {\n selectedOption.value = val;\n\n emit('change', {\n value: internalInput.value,\n option: selectedOption.value,\n isValueChange: false,\n type: 'select',\n });\n emit('update:model-value', {\n value: internalInput.value,\n option: selectedOption.value,\n isValueChange: false,\n type: 'select',\n });\n }\n\n watchEffect(() => {\n if (!selectedOption.value) {\n selectedOption.value = props.options[0];\n }\n });\n\n watch(\n () => props.modelValue.value,\n () => {\n internalInput.value = props.modelValue.value;\n },\n { immediate: true },\n );\n\n watch(\n () => props.modelValue.option,\n () => {\n selectedOption.value = props.modelValue.option;\n },\n { immediate: true },\n );\n\n if (attrs.value) {\n throw new Error('ll-input-options: use :model-value or v-model instead of :value.');\n }\n\n if (attrs.onInput) {\n throw new Error('ll-input-options: use the @update:model-value event instead of @input');\n }\n</script>\n\n<template>\n <Field v-bind=\"props\" class=\"stash-input-options\" data-test=\"stash-input-options\">\n <template #default=\"{ fieldId, labelId }\">\n <div v-if=\"props.isReadOnly\" class=\"tw-flex tw-h-input tw-items-center tw-text-sm\">\n <span :id=\"fieldId\" :aria-labelledby=\"labelId\" class=\"tw-h-min\"\n >{{ internalInput || 0 }} {{ selectedOption?.name }}</span\n >\n </div>\n <div v-else class=\"tw-flex\" :class=\"{ [classes['has-error']]: !!props.errorText }\">\n <Input\n :id=\"fieldId\"\n class=\"stash-input-options__input -tw-mr-[1px] tw-inline-block tw-flex-1\"\n :class=\"[classes.input, { 'tw-z-control': isInputFocused }]\"\n data-test=\"stash-input-options|input\"\n :type=\"props.type\"\n :model-value=\"internalInput\"\n :disabled=\"props.isDisabled || props.disabled\"\n :placeholder=\"props.placeholder\"\n @change=\"handleInputChange\"\n @update:model-value=\"handleInput\"\n @blur=\"isInputFocused = false\"\n @focus=\"isInputFocused = true\"\n />\n\n <Select\n v-bind=\"selectAttrs\"\n single\n hide-search\n prevent-empty\n class=\"stash-input-options__select tw-min-w-20\"\n data-test=\"stash-input-options|select\"\n :class=\"classes.select\"\n :no-truncate=\"noTruncate\"\n :options=\"options\"\n :model-value=\"selectedOption\"\n :disabled=\"props.isDisabled || props.disabled\"\n @update:model-value=\"handleSelectChange\"\n />\n </div>\n </template>\n <template v-if=\"slots.hint\" #hint>\n <!-- @slot Hint slot for rendering text below the input -->\n <slot name=\"hint\"></slot>\n </template>\n </Field>\n</template>\n\n<style module>\n .input input {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n }\n\n .select :global(.stash-select__content) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n }\n\n .select:global(.stash-select--active .stash-select__content) {\n min-width: 0;\n }\n\n .has-error input,\n .has-error input:hover:not(:focus),\n .has-error :global(.stash-select__content),\n .has-error :global(.stash-select__content:hover:not(:focus)) {\n border-color: var(--color-red-500);\n }\n</style>\n"],"names":["props","__props","emit","__emit","attrs","useAttrs","slots","useSlots","classes","useCssModule","internalInput","ref","isInputFocused","selectedOption","selectAttrs","computed","disabled","displayBy","trackBy","handleInput","val","handleInputChange","handleSelectChange","watchEffect","watch"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DE,UAAMA,IAAQC,GAQRC,IAAOC,GAiBPC,IAAQC,KACRC,IAAQC,KACRC,IAAUC,KACVC,IAAgBC,KAChBC,IAAiBD,EAAI,EAAK,GAC1BE,IAAiBF,KAEjBG,IAAcC,EAAS,MAAM;AACjC,YAAM,EAAE,UAAAC,GAAU,WAAAC,GAAW,SAAAC,EAAA,IAAYd;AAElC,aAAA,EAAE,UAAAY,GAAU,WAAAC,GAAW,SAAAC;IAAQ,CACvC;AAGD,aAASC,EAAYC,GAAuB;AAC5B,MAAAV,EAAA,QAAQ,OAAOU,CAAG,GAEhClB,EAAK,sBAAsB;AAAA,QACzB,OAAOQ,EAAc;AAAA,QACrB,QAAQG,EAAe;AAAA,QACvB,eAAe;AAAA,QACf,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAGA,aAASQ,IAAoB;AAC3B,MAAAnB,EAAK,UAAU;AAAA,QACb,OAAOQ,EAAc;AAAA,QACrB,QAAQG,EAAe;AAAA,QACvB,eAAe;AAAA,QACf,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAEA,aAASS,EAAmBF,GAAc;AACxC,MAAAP,EAAe,QAAQO,GAEvBlB,EAAK,UAAU;AAAA,QACb,OAAOQ,EAAc;AAAA,QACrB,QAAQG,EAAe;AAAA,QACvB,eAAe;AAAA,QACf,MAAM;AAAA,MAAA,CACP,GACDX,EAAK,sBAAsB;AAAA,QACzB,OAAOQ,EAAc;AAAA,QACrB,QAAQG,EAAe;AAAA,QACvB,eAAe;AAAA,QACf,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAwBA,QAtBAU,EAAY,MAAM;AACZ,MAACV,EAAe,UACHA,EAAA,QAAQb,EAAM,QAAQ,CAAC;AAAA,IACxC,CACD,GAEDwB;AAAA,MACE,MAAMxB,EAAM,WAAW;AAAA,MACvB,MAAM;AACU,QAAAU,EAAA,QAAQV,EAAM,WAAW;AAAA,MACzC;AAAA,MACA,EAAE,WAAW,GAAK;AAAA,IAAA,GAGpBwB;AAAA,MACE,MAAMxB,EAAM,WAAW;AAAA,MACvB,MAAM;AACW,QAAAa,EAAA,QAAQb,EAAM,WAAW;AAAA,MAC1C;AAAA,MACA,EAAE,WAAW,GAAK;AAAA,IAAA,GAGhBI,EAAM;AACF,YAAA,IAAI,MAAM,kEAAkE;AAGpF,QAAIA,EAAM;AACF,YAAA,IAAI,MAAM,uEAAuE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"InputOptions.js","sources":["../src/components/InputOptions/InputOptions.vue"],"sourcesContent":["<script lang=\"ts\">\n import Field, { type FieldProps } from '../Field/Field.vue';\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n type Option = any;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n type SelectedOption = any;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n export interface InputOptionsProps extends FieldProps {\n /**\n * The current value inclusive of the input & select\n */\n modelValue?: { value: string; option?: SelectedOption };\n\n /**\n * Input type\n */\n type?: string extends 'button' | 'checkbox' | 'radio' | 'submit' ? never : string;\n\n /**\n * Prevents the Selected Option from being truncated, if true\n */\n noTruncate?: boolean;\n\n /**\n * Options for the select\n */\n options?: Option[];\n\n /**\n * Placeholder text for the input\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 * If `options` are an object, this is what prop to use for display.\n */\n displayBy?: string;\n\n /**\n * Default field to track selected options by.\n */\n trackBy?: string;\n }\n</script>\n\n<script lang=\"ts\" setup>\n import { ref, useAttrs, useCssModule, useSlots, watch, watchEffect } from 'vue';\n\n import Input from '../Input/Input.vue';\n import Select from '../Select/Select.vue';\n\n defineOptions({\n name: 'll-input-options',\n });\n\n const props = withDefaults(defineProps<InputOptionsProps>(), {\n modelValue: () => ({ value: '', option: undefined }),\n noTruncate: false,\n options: () => [],\n type: 'text',\n placeholder: undefined,\n displayBy: undefined,\n trackBy: undefined,\n });\n\n const emit = defineEmits<{\n /**\n * Emitted when the model value changes\n */\n (\n e: 'update:model-value',\n v: { value?: string; option?: SelectedOption; isValueChange: boolean; type: 'input' | 'select' },\n ): void;\n /**\n * Emitted when either the input or select changes\n */\n (\n e: 'change',\n v: { value?: string; option?: SelectedOption; isValueChange: boolean; type: 'input' | 'select' },\n ): void;\n }>();\n\n const attrs = useAttrs();\n const slots = useSlots();\n const classes = useCssModule();\n const internalInput = ref<string>();\n const isInputFocused = ref(false);\n const selectedOption = ref<Option | undefined>();\n\n // Input value changed\n function handleInput(val?: string | number) {\n internalInput.value = String(val);\n\n emit('update:model-value', {\n value: internalInput.value,\n option: selectedOption.value,\n isValueChange: true,\n type: 'input',\n });\n }\n\n // Input blurred\n function handleInputChange() {\n emit('change', {\n value: internalInput.value,\n option: selectedOption.value,\n isValueChange: true,\n type: 'input',\n });\n }\n\n function handleSelectChange(val?: Option) {\n selectedOption.value = val;\n\n emit('change', {\n value: internalInput.value,\n option: selectedOption.value,\n isValueChange: false,\n type: 'select',\n });\n emit('update:model-value', {\n value: internalInput.value,\n option: selectedOption.value,\n isValueChange: false,\n type: 'select',\n });\n }\n\n watchEffect(() => {\n if (!selectedOption.value) {\n selectedOption.value = props.options[0];\n }\n });\n\n watch(\n () => props.modelValue.value,\n () => {\n internalInput.value = props.modelValue.value;\n },\n { immediate: true },\n );\n\n watch(\n () => props.modelValue.option,\n () => {\n selectedOption.value = props.modelValue.option;\n },\n { immediate: true },\n );\n\n if (attrs.value) {\n throw new Error('ll-input-options: use :model-value or v-model instead of :value.');\n }\n\n if (attrs.onInput) {\n throw new Error('ll-input-options: use the @update:model-value event instead of @input');\n }\n</script>\n\n<template>\n <Field v-bind=\"props\" class=\"stash-input-options\" data-test=\"stash-input-options\">\n <template #default=\"{ fieldId, labelId }\">\n <div v-if=\"props.isReadOnly\" class=\"tw-flex tw-h-input tw-items-center tw-text-sm\">\n <span :id=\"fieldId\" :aria-labelledby=\"labelId\" class=\"tw-h-min\"\n >{{ internalInput || 0 }} {{ selectedOption?.name }}</span\n >\n </div>\n <div v-else class=\"tw-flex\" :class=\"{ [classes['has-error']]: !!props.errorText }\">\n <Input\n :id=\"fieldId\"\n class=\"stash-input-options__input -tw-mr-[1px] tw-inline-block tw-flex-1\"\n :class=\"[classes.input, { 'tw-z-control': isInputFocused }]\"\n data-test=\"stash-input-options|input\"\n :type=\"props.type\"\n :model-value=\"internalInput\"\n :disabled=\"props.isDisabled || props.disabled\"\n :placeholder=\"props.placeholder\"\n @change=\"handleInputChange\"\n @update:model-value=\"handleInput\"\n @blur=\"isInputFocused = false\"\n @focus=\"isInputFocused = true\"\n />\n\n <Select\n single\n hide-search\n prevent-empty\n class=\"stash-input-options__select tw-min-w-20\"\n data-test=\"stash-input-options|select\"\n :class=\"classes.select\"\n :no-truncate=\"noTruncate\"\n :options=\"options\"\n :model-value=\"selectedOption\"\n :display-by=\"props.displayBy\"\n :track-by=\"props.trackBy\"\n :disabled=\"props.isDisabled || props.disabled\"\n @update:model-value=\"handleSelectChange\"\n />\n </div>\n </template>\n <template v-if=\"slots.hint\" #hint>\n <!-- @slot Hint slot for rendering text below the input -->\n <slot name=\"hint\"></slot>\n </template>\n </Field>\n</template>\n\n<style module>\n .input input {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n }\n\n .select :global(.stash-select__content) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n }\n\n .select:global(.stash-select--active .stash-select__content) {\n min-width: 0;\n }\n\n .has-error input,\n .has-error input:hover:not(:focus),\n .has-error :global(.stash-select__content),\n .has-error :global(.stash-select__content:hover:not(:focus)) {\n border-color: var(--color-red-500);\n }\n</style>\n"],"names":["props","__props","emit","__emit","attrs","useAttrs","slots","useSlots","classes","useCssModule","internalInput","ref","isInputFocused","selectedOption","handleInput","val","handleInputChange","handleSelectChange","watchEffect","watch"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DE,UAAMA,IAAQC,GAURC,IAAOC,GAiBPC,IAAQC,KACRC,IAAQC,KACRC,IAAUC,KACVC,IAAgBC,KAChBC,IAAiBD,EAAI,EAAK,GAC1BE,IAAiBF;AAGvB,aAASG,EAAYC,GAAuB;AAC5B,MAAAL,EAAA,QAAQ,OAAOK,CAAG,GAEhCb,EAAK,sBAAsB;AAAA,QACzB,OAAOQ,EAAc;AAAA,QACrB,QAAQG,EAAe;AAAA,QACvB,eAAe;AAAA,QACf,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAGA,aAASG,IAAoB;AAC3B,MAAAd,EAAK,UAAU;AAAA,QACb,OAAOQ,EAAc;AAAA,QACrB,QAAQG,EAAe;AAAA,QACvB,eAAe;AAAA,QACf,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAEA,aAASI,EAAmBF,GAAc;AACxC,MAAAF,EAAe,QAAQE,GAEvBb,EAAK,UAAU;AAAA,QACb,OAAOQ,EAAc;AAAA,QACrB,QAAQG,EAAe;AAAA,QACvB,eAAe;AAAA,QACf,MAAM;AAAA,MAAA,CACP,GACDX,EAAK,sBAAsB;AAAA,QACzB,OAAOQ,EAAc;AAAA,QACrB,QAAQG,EAAe;AAAA,QACvB,eAAe;AAAA,QACf,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AAwBA,QAtBAK,EAAY,MAAM;AACZ,MAACL,EAAe,UACHA,EAAA,QAAQb,EAAM,QAAQ,CAAC;AAAA,IACxC,CACD,GAEDmB;AAAA,MACE,MAAMnB,EAAM,WAAW;AAAA,MACvB,MAAM;AACU,QAAAU,EAAA,QAAQV,EAAM,WAAW;AAAA,MACzC;AAAA,MACA,EAAE,WAAW,GAAK;AAAA,IAAA,GAGpBmB;AAAA,MACE,MAAMnB,EAAM,WAAW;AAAA,MACvB,MAAM;AACW,QAAAa,EAAA,QAAQb,EAAM,WAAW;AAAA,MAC1C;AAAA,MACA,EAAE,WAAW,GAAK;AAAA,IAAA,GAGhBI,EAAM;AACF,YAAA,IAAI,MAAM,kEAAkE;AAGpF,QAAIA,EAAM;AACF,YAAA,IAAI,MAAM,uEAAuE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -41,6 +41,8 @@ noTruncate: boolean;
41
41
  options: () => never[];
42
42
  type: string;
43
43
  placeholder: undefined;
44
+ displayBy: undefined;
45
+ trackBy: undefined;
44
46
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
45
47
  "update:model-value": (v: {
46
48
  value?: string | undefined;
@@ -63,6 +65,8 @@ noTruncate: boolean;
63
65
  options: () => never[];
64
66
  type: string;
65
67
  placeholder: undefined;
68
+ displayBy: undefined;
69
+ trackBy: undefined;
66
70
  }>>> & Readonly<{
67
71
  onChange?: ((v: {
68
72
  value?: string | undefined;
@@ -78,7 +82,9 @@ type: 'input' | 'select';
78
82
  }) => any) | undefined;
79
83
  }>, {
80
84
  type: string;
85
+ trackBy: string;
81
86
  placeholder: string;
87
+ displayBy: string;
82
88
  options: any[];
83
89
  modelValue: {
84
90
  value: string;
@@ -169,13 +175,13 @@ export declare interface InputOptionsProps extends FieldProps {
169
175
  */
170
176
  placeholder?: string;
171
177
  /**
172
- * Indicates whether the inputOptions is disabled.
178
+ * If `options` are an object, this is what prop to use for display.
173
179
  */
174
- disabled?: boolean;
180
+ displayBy?: string;
175
181
  /**
176
- * Indicates whether the inputOptions is read-only.
182
+ * Default field to track selected options by.
177
183
  */
178
- isReadOnly?: boolean;
184
+ trackBy?: string;
179
185
  }
180
186
 
181
187
  declare type Option_2 = any;
@@ -2016,6 +2016,10 @@ type: PropType<string>;
2016
2016
  id: {
2017
2017
  type: PropType<string>;
2018
2018
  };
2019
+ trackBy: {
2020
+ type: PropType<string>;
2021
+ default: undefined;
2022
+ };
2019
2023
  isRequired: {
2020
2024
  type: PropType<boolean>;
2021
2025
  };
@@ -2044,6 +2048,10 @@ placeholder: {
2044
2048
  type: PropType<string>;
2045
2049
  default: undefined;
2046
2050
  };
2051
+ displayBy: {
2052
+ type: PropType<string>;
2053
+ default: undefined;
2054
+ };
2047
2055
  options: {
2048
2056
  type: PropType<any[]>;
2049
2057
  default: () => never[];
@@ -2055,9 +2063,7 @@ option?: any;
2055
2063
  }>;
2056
2064
  default: () => {
2057
2065
  value: string;
2058
- option: undefined; /**
2059
- * Validation schema function that returns an object
2060
- */
2066
+ option: undefined;
2061
2067
  };
2062
2068
  };
2063
2069
  noTruncate: {
@@ -2073,20 +2079,20 @@ type: "input" | "select";
2073
2079
  }) => any) | undefined;
2074
2080
  "onUpdate:model-value"?: ((v: {
2075
2081
  value?: string | undefined;
2076
- option?: any;
2077
- isValueChange: boolean;
2078
- type: "input" | "select"; /**
2082
+ option?: any; /**
2079
2083
  * Hide the Select All checkbox for bulk actions
2080
2084
  */
2085
+ isValueChange: boolean;
2086
+ type: "input" | "select";
2081
2087
  }) => any) | undefined;
2082
2088
  }>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
2083
2089
  "update:model-value": (v: {
2084
2090
  value?: string | undefined;
2085
- option?: any;
2086
- isValueChange: boolean;
2087
- type: "input" | "select"; /**
2091
+ option?: any; /**
2088
2092
  * Hide the Select All checkbox for bulk actions
2089
2093
  */
2094
+ isValueChange: boolean;
2095
+ type: "input" | "select";
2090
2096
  }) => void;
2091
2097
  change: (v: {
2092
2098
  value?: string | undefined;
@@ -2096,7 +2102,9 @@ type: "input" | "select";
2096
2102
  }) => void;
2097
2103
  }, PublicProps, {
2098
2104
  type: string;
2105
+ trackBy: string;
2099
2106
  placeholder: string;
2107
+ displayBy: string;
2100
2108
  options: any[];
2101
2109
  modelValue: {
2102
2110
  value: string;
@@ -2127,6 +2135,10 @@ type: PropType<string>;
2127
2135
  id: {
2128
2136
  type: PropType<string>;
2129
2137
  };
2138
+ trackBy: {
2139
+ type: PropType<string>;
2140
+ default: undefined;
2141
+ };
2130
2142
  isRequired: {
2131
2143
  type: PropType<boolean>;
2132
2144
  };
@@ -2155,6 +2167,10 @@ placeholder: {
2155
2167
  type: PropType<string>;
2156
2168
  default: undefined;
2157
2169
  };
2170
+ displayBy: {
2171
+ type: PropType<string>;
2172
+ default: undefined;
2173
+ };
2158
2174
  options: {
2159
2175
  type: PropType<any[]>;
2160
2176
  default: () => never[];
@@ -2166,9 +2182,7 @@ option?: any;
2166
2182
  }>;
2167
2183
  default: () => {
2168
2184
  value: string;
2169
- option: undefined; /**
2170
- * Validation schema function that returns an object
2171
- */
2185
+ option: undefined;
2172
2186
  };
2173
2187
  };
2174
2188
  noTruncate: {
@@ -2184,15 +2198,17 @@ type: "input" | "select";
2184
2198
  }) => any) | undefined;
2185
2199
  "onUpdate:model-value"?: ((v: {
2186
2200
  value?: string | undefined;
2187
- option?: any;
2188
- isValueChange: boolean;
2189
- type: "input" | "select"; /**
2201
+ option?: any; /**
2190
2202
  * Hide the Select All checkbox for bulk actions
2191
2203
  */
2204
+ isValueChange: boolean;
2205
+ type: "input" | "select";
2192
2206
  }) => any) | undefined;
2193
2207
  }>, {}, {}, {}, {}, {
2194
2208
  type: string;
2209
+ trackBy: string;
2195
2210
  placeholder: string;
2211
+ displayBy: string;
2196
2212
  options: any[];
2197
2213
  modelValue: {
2198
2214
  value: string;
@@ -2220,6 +2236,10 @@ type: PropType<string>;
2220
2236
  id: {
2221
2237
  type: PropType<string>;
2222
2238
  };
2239
+ trackBy: {
2240
+ type: PropType<string>;
2241
+ default: undefined;
2242
+ };
2223
2243
  isRequired: {
2224
2244
  type: PropType<boolean>;
2225
2245
  };
@@ -2248,6 +2268,10 @@ placeholder: {
2248
2268
  type: PropType<string>;
2249
2269
  default: undefined;
2250
2270
  };
2271
+ displayBy: {
2272
+ type: PropType<string>;
2273
+ default: undefined;
2274
+ };
2251
2275
  options: {
2252
2276
  type: PropType<any[]>;
2253
2277
  default: () => never[];
@@ -2259,9 +2283,7 @@ option?: any;
2259
2283
  }>;
2260
2284
  default: () => {
2261
2285
  value: string;
2262
- option: undefined; /**
2263
- * Validation schema function that returns an object
2264
- */
2286
+ option: undefined;
2265
2287
  };
2266
2288
  };
2267
2289
  noTruncate: {
@@ -2277,20 +2299,20 @@ type: "input" | "select";
2277
2299
  }) => any) | undefined;
2278
2300
  "onUpdate:model-value"?: ((v: {
2279
2301
  value?: string | undefined;
2280
- option?: any;
2281
- isValueChange: boolean;
2282
- type: "input" | "select"; /**
2302
+ option?: any; /**
2283
2303
  * Hide the Select All checkbox for bulk actions
2284
2304
  */
2305
+ isValueChange: boolean;
2306
+ type: "input" | "select";
2285
2307
  }) => any) | undefined;
2286
2308
  }>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
2287
2309
  "update:model-value": (v: {
2288
2310
  value?: string | undefined;
2289
- option?: any;
2290
- isValueChange: boolean;
2291
- type: "input" | "select"; /**
2311
+ option?: any; /**
2292
2312
  * Hide the Select All checkbox for bulk actions
2293
2313
  */
2314
+ isValueChange: boolean;
2315
+ type: "input" | "select";
2294
2316
  }) => void;
2295
2317
  change: (v: {
2296
2318
  value?: string | undefined;
@@ -2300,7 +2322,9 @@ type: "input" | "select";
2300
2322
  }) => void;
2301
2323
  }, string, {
2302
2324
  type: string;
2325
+ trackBy: string;
2303
2326
  placeholder: string;
2327
+ displayBy: string;
2304
2328
  options: any[];
2305
2329
  modelValue: {
2306
2330
  value: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leaflink/stash",
3
- "version": "50.0.7",
3
+ "version": "50.1.0",
4
4
  "description": "LeafLink's design system.",
5
5
  "homepage": "https://stash.leaflink.com",
6
6
  "main": "./dist/index.ts",