tide-design-system 2.4.5 → 2.4.7

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.
Files changed (56) hide show
  1. package/.storybook/main.ts +1 -0
  2. package/dist/css/reset.css +1 -1
  3. package/dist/css/utilities-responsive.css +0 -546
  4. package/dist/style.css +1 -1
  5. package/dist/tide-design-system.cjs +2 -2
  6. package/dist/tide-design-system.esm.d.ts +62 -6
  7. package/dist/tide-design-system.esm.js +1821 -1720
  8. package/dist/utilities/storybook.ts +6 -2
  9. package/dist/utilities/validation.ts +1 -1
  10. package/index.ts +8 -5
  11. package/package.json +1 -1
  12. package/src/assets/css/reset.css +1 -1
  13. package/src/assets/css/utilities-responsive.css +0 -546
  14. package/src/components/InternalBaseLink.vue +11 -0
  15. package/src/components/TideBreadCrumbs.vue +3 -2
  16. package/src/components/TideButton.vue +17 -4
  17. package/src/components/TideButtonIcon.vue +15 -2
  18. package/src/components/TideButtonPagination.vue +16 -16
  19. package/src/components/TideButtonSegmented.vue +1 -0
  20. package/src/components/TideCard.vue +12 -2
  21. package/src/components/TideCarousel.vue +10 -5
  22. package/src/components/TideChipAction.vue +7 -1
  23. package/src/components/TideChipFilter.vue +1 -0
  24. package/src/components/TideChipInput.vue +1 -0
  25. package/src/components/TideIcon.vue +8 -9
  26. package/src/components/TideImage.vue +9 -9
  27. package/src/components/TideInputText.vue +2 -0
  28. package/src/components/TideInputTextDeprecated.vue +2 -0
  29. package/src/components/TideInputTextarea.vue +2 -2
  30. package/src/components/TideLink.vue +7 -1
  31. package/src/components/TideMenuItem.vue +83 -0
  32. package/src/components/TideModal.vue +91 -85
  33. package/src/components/TideSeoLinks.vue +3 -2
  34. package/src/components/TideSheet.vue +5 -3
  35. package/src/components/TideSwitch.vue +1 -0
  36. package/src/composables/useTideConfig.ts +23 -0
  37. package/src/stories/TideButtonPagination.stories.ts +6 -6
  38. package/src/stories/TideCarousel.stories.ts +0 -1
  39. package/src/stories/TideInputCheckbox.stories.ts +58 -23
  40. package/src/stories/TideInputRadio.stories.ts +39 -30
  41. package/src/stories/TideInputSelect.stories.ts +51 -27
  42. package/src/stories/TideInputText.stories.ts +83 -23
  43. package/src/stories/TideInputTextarea.stories.ts +66 -17
  44. package/src/stories/TideLink.stories.ts +1 -14
  45. package/src/stories/TideMenuItem.stories.ts +117 -0
  46. package/src/stories/TidePagination.stories.ts +2 -2
  47. package/src/stories/TidePopover.stories.ts +1 -1
  48. package/src/types/Badge.ts +4 -0
  49. package/src/types/Element.ts +2 -2
  50. package/src/types/Formatted.ts +1 -0
  51. package/src/types/Storybook.ts +4 -6
  52. package/src/types/Type.ts +6 -0
  53. package/src/types/Validation.ts +1 -0
  54. package/src/utilities/storybook.ts +6 -2
  55. package/src/utilities/validation.ts +1 -1
  56. package/tests/InternalBaseLink.spec.ts +61 -0
@@ -3,11 +3,11 @@ export const ELEMENT = {
3
3
  LINK: 'a',
4
4
  } as const;
5
5
 
6
- export const ELEMENT_TEXT_AS_ICON = {
6
+ export const ELEMENT_BROAD = {
7
7
  BUTTON: 'button',
8
8
  DIV: 'div',
9
9
  LINK: 'a',
10
10
  } as const;
11
11
 
12
12
  export type Element = (typeof ELEMENT)[keyof typeof ELEMENT];
13
- export type ElementTextAsIcon = (typeof ELEMENT_TEXT_AS_ICON)[keyof typeof ELEMENT_TEXT_AS_ICON];
13
+ export type ElementBroad = (typeof ELEMENT_BROAD)[keyof typeof ELEMENT_BROAD];
@@ -19,4 +19,5 @@ export const FORMAT_REGEX = {
19
19
  numberFormatted: /^$|(?=.)^\$?(([1-9][0-9]{0,2}(,[0-9]{3})*)|0)?(\.[0-9]{1,2})?$/,
20
20
  phone: /^(?:\d{3}-\d{3}-\d{4}|\d{1}-\d{3}-\d{3}-\d{4})?$/,
21
21
  price: /(?=.)^\$?(([1-9][0-9]{0,2}(,[0-9]{3})*)|0)?(\.[0-9]{1,2})?$/,
22
+ zip: /^\d{5}$/,
22
23
  };
@@ -22,6 +22,10 @@ export const BADGE_TRUSTED = {
22
22
  YEARS_5: '5',
23
23
  YEARS_10: '10',
24
24
  YEARS_15: '15',
25
+ YEARS_20: '20',
26
+ YEARS_25: '25',
27
+ YEARS_30: '30',
28
+ YEARS_35: '35',
25
29
  };
26
30
 
27
31
  export const BG = {
@@ -115,12 +119,6 @@ export const GAP = {
115
119
  '0.25 REM': CSS.GAP.QUARTER,
116
120
  };
117
121
 
118
- export const LINK_SIZE = {
119
- TWELVE: CSS.FONT.SIZE.TWELVE,
120
- FOURTEEN: CSS.FONT.SIZE.FOURTEEN,
121
- SIXTEEN: CSS.FONT.SIZE.SIXTEEN,
122
- };
123
-
124
122
  export const MARGIN = {
125
123
  'Full 4 REM': CSS.MARGIN.FULL.FOUR,
126
124
  'Full 2 REM': CSS.MARGIN.FULL.TWO,
@@ -0,0 +1,6 @@
1
+ export const BUTTON_TYPE = {
2
+ BUTTON: 'button',
3
+ SUBMIT: 'submit',
4
+ } as const;
5
+
6
+ export type ButtonType = (typeof BUTTON_TYPE)[keyof typeof BUTTON_TYPE];
@@ -7,6 +7,7 @@ export const VALIDATOR = {
7
7
  EMAIL: checkFormat(FORMAT_REGEX.email, 'Enter a valid email address (e.g. name@example.com)'),
8
8
  NUMBER: checkFormat(FORMAT_REGEX.numberFormatted, 'Enter a valid number'),
9
9
  PHONE: checkFormat(FORMAT_REGEX.phone, 'Enter a valid phone number'),
10
+ ZIP: checkFormat(FORMAT_REGEX.zip, 'Enter a valid Zip code'),
10
11
  } as const;
11
12
 
12
13
  export type ValidationError = string | boolean;
@@ -1,4 +1,4 @@
1
- import { ELEMENT, ELEMENT_TEXT_AS_ICON } from '@/types/Element';
1
+ import { ELEMENT, ELEMENT_BROAD } from '@/types/Element';
2
2
  import { BOOLEAN, BOOLEAN_UNREQUIRED, NoneAsEmpty, NoneAsUndefined } from '@/types/Storybook';
3
3
  import { CSS } from '@/types/Styles';
4
4
  import { formatKebabCase } from '@/utilities/format';
@@ -61,6 +61,7 @@ export const change = {
61
61
  isEmit: true,
62
62
  name: 'change',
63
63
  table: {
64
+ category: 'Events',
64
65
  defaultValue: { summary: 'None' },
65
66
  type: { summary: '() => void' },
66
67
  },
@@ -71,6 +72,7 @@ export const click = {
71
72
  description: 'JS code or function to execute on click event',
72
73
  isEmit: true,
73
74
  table: {
75
+ category: 'Events',
74
76
  defaultValue: { summary: 'None' },
75
77
  type: { summary: '() => void' },
76
78
  },
@@ -81,6 +83,7 @@ export const close = {
81
83
  description: 'JS code or function to execute on close event',
82
84
  isEmit: true,
83
85
  table: {
86
+ category: 'Events',
84
87
  defaultValue: { summary: 'None' },
85
88
  type: { summary: '() => void' },
86
89
  },
@@ -90,6 +93,7 @@ export const dataTrack = {
90
93
  control: 'text',
91
94
  description: 'Data attribute for external tracking',
92
95
  table: {
96
+ category: 'Native',
93
97
  defaultValue: { summary: 'None' },
94
98
  type: { summary: 'string' },
95
99
  },
@@ -252,7 +256,7 @@ export const formatSnippet = (code: string, context: StoryContext) => {
252
256
  if (
253
257
  isClick &&
254
258
  value &&
255
- (!args.element || args.element === ELEMENT.BUTTON || args.element === ELEMENT_TEXT_AS_ICON.BUTTON)
259
+ (!args.element || args.element === ELEMENT.BUTTON || args.element === ELEMENT_BROAD.BUTTON)
256
260
  ) {
257
261
  return `@click="${value}"`;
258
262
  }
@@ -70,7 +70,7 @@ export const getFieldValidationResult = ({
70
70
  }
71
71
 
72
72
  // all other prop-based errors come last
73
- if (required && value.value.trim() === '') {
73
+ if (required && value.value?.trim() === '') {
74
74
  return VALIDATION_RESULT.REQUIRED;
75
75
  }
76
76
 
@@ -0,0 +1,61 @@
1
+ /// <reference types="vitest/globals" />
2
+
3
+ import { mount } from '@vue/test-utils';
4
+ import { describe, expect, it } from 'vitest';
5
+ import { defineComponent, h, markRaw } from 'vue';
6
+
7
+ import InternalBaseLink from '@/components/InternalBaseLink.vue';
8
+ import { provideTideConfig } from '@/composables/useTideConfig';
9
+
10
+ // @vitest-environment jsdom
11
+
12
+ /* eslint-disable vue/one-component-per-file */
13
+ const TestWrapper = defineComponent({
14
+ props: {
15
+ config: { type: Object, default: () => ({}) },
16
+ },
17
+ setup(props, { slots }) {
18
+ provideTideConfig(props.config);
19
+ return () => h(InternalBaseLink, null, slots);
20
+ },
21
+ });
22
+ /* eslint-enable vue/one-component-per-file */
23
+
24
+ describe('InternalBaseLink', () => {
25
+ it('renders default <a> when no provider is used', () => {
26
+ const wrapper = mount(InternalBaseLink, {
27
+ slots: { default: 'Hello' },
28
+ });
29
+
30
+ expect(wrapper.element.tagName.toLowerCase()).toBe('a');
31
+ expect(wrapper.text()).toBe('Hello');
32
+ });
33
+
34
+ it('renders a provided custom link component', () => {
35
+ const CustomLink = markRaw(
36
+ /* eslint-disable vue/one-component-per-file */
37
+ defineComponent({
38
+ name: 'CustomLink',
39
+ render() {
40
+ return h('custom-link', {}, this.$slots.default?.());
41
+ },
42
+ })
43
+ /* eslint-enable vue/one-component-per-file */
44
+ );
45
+
46
+ const wrapper = mount(TestWrapper, {
47
+ props: {
48
+ config: {
49
+ linkComponent: CustomLink,
50
+ },
51
+ },
52
+ slots: {
53
+ default: 'Custom Content',
54
+ },
55
+ });
56
+
57
+ const btn = wrapper.find('custom-link');
58
+ expect(btn.exists()).toBe(true);
59
+ expect(btn.text()).toBe('Custom Content');
60
+ });
61
+ });