@citizenplane/pimp 16.0.3 → 16.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/pimp.es.js +781 -757
  2. package/dist/pimp.umd.js +21 -21
  3. package/dist/style.css +1 -1
  4. package/package.json +10 -8
  5. package/src/components/CpDate.vue +3 -1
  6. package/src/components/CpHeading.vue +4 -5
  7. package/src/components/CpMultiselect.vue +2 -5
  8. package/src/components/CpTable.vue +4 -2
  9. package/src/components/CpTelInput.vue +18 -12
  10. package/src/components/CpText.vue +141 -0
  11. package/src/components/CpToast.vue +1 -1
  12. package/src/components/CpTransitionExpand.vue +23 -20
  13. package/src/components/index.ts +2 -0
  14. package/src/libs/CoreDatepicker.vue +1 -0
  15. package/src/stories/BaseInputLabel.stories.ts +36 -9
  16. package/src/stories/Colors.mdx +9 -0
  17. package/src/stories/Colors.stories.ts +177 -0
  18. package/src/stories/CpAccordion.stories.ts +188 -159
  19. package/src/stories/CpAccordionGroup.stories.ts +51 -95
  20. package/src/stories/CpAirlineLogo.stories.ts +52 -28
  21. package/src/stories/CpAlert.stories.ts +196 -159
  22. package/src/stories/CpBadge.stories.ts +260 -194
  23. package/src/stories/CpButton.stories.ts +257 -426
  24. package/src/stories/CpCheckbox.stories.ts +102 -30
  25. package/src/stories/CpContextualMenu.stories.ts +14 -9
  26. package/src/stories/CpDate.stories.ts +53 -26
  27. package/src/stories/CpDatepicker.stories.ts +53 -80
  28. package/src/stories/CpDialog.stories.ts +23 -2
  29. package/src/stories/CpHeading.stories.ts +60 -20
  30. package/src/stories/CpIcon.stories.ts +98 -31
  31. package/src/stories/CpInput.stories.ts +164 -73
  32. package/src/stories/CpItemActions.stories.ts +23 -12
  33. package/src/stories/CpLoader.stories.ts +55 -7
  34. package/src/stories/CpMenuItem.stories.ts +53 -27
  35. package/src/stories/CpMultiselect.stories.ts +53 -72
  36. package/src/stories/CpPartnerBadge.stories.ts +58 -76
  37. package/src/stories/CpRadio.stories.ts +45 -49
  38. package/src/stories/CpRadioGroup.stories.ts +47 -40
  39. package/src/stories/CpSelect.stories.ts +108 -34
  40. package/src/stories/CpSelectMenu.stories.ts +66 -55
  41. package/src/stories/CpSelectableButton.stories.ts +170 -81
  42. package/src/stories/CpSwitch.stories.ts +136 -134
  43. package/src/stories/CpTable.stories.ts +69 -13
  44. package/src/stories/CpTableEmptyState.stories.ts +11 -7
  45. package/src/stories/CpTabs.stories.ts +23 -5
  46. package/src/stories/CpTelInput.stories.ts +28 -19
  47. package/src/stories/CpText.stories.ts +131 -0
  48. package/src/stories/CpTextarea.stories.ts +74 -27
  49. package/src/stories/CpToast.stories.ts +75 -109
  50. package/src/stories/CpTooltip.stories.ts +82 -77
  51. package/src/stories/CpTransitionCounter.stories.ts +5 -1
  52. package/src/stories/CpTransitionExpand.stories.ts +12 -7
  53. package/src/stories/CpTransitionListItems.stories.ts +6 -1
  54. package/src/stories/CpTransitionSize.stories.ts +9 -1
  55. package/src/stories/CpTransitionSlide.stories.ts +5 -1
  56. package/src/stories/CpTransitionTabContent.stories.ts +5 -1
  57. package/src/stories/Dimensions.mdx +9 -0
  58. package/src/stories/Dimensions.stories.ts +119 -0
  59. package/src/stories/Easings.mdx +9 -0
  60. package/src/stories/Easings.stories.ts +101 -0
  61. package/src/stories/FocusRings.mdx +9 -0
  62. package/src/stories/FocusRings.stories.ts +74 -0
  63. package/src/stories/Shadows.mdx +9 -0
  64. package/src/stories/Shadows.stories.ts +100 -0
  65. package/src/stories/Typography.mdx +9 -0
  66. package/src/stories/Typography.stories.ts +181 -0
  67. package/src/stories/documentationStyles.ts +2 -10
  68. package/src/stories/tokenUtils.ts +259 -0
  69. package/src/types/primevue-toasteventbus.d.ts +14 -0
  70. package/tsconfig.json +1 -0
  71. package/.lintstagedrc.json +0 -4
@@ -1,11 +1,13 @@
1
1
  import { ref } from 'vue'
2
2
 
3
- import type { Meta, StoryObj } from '@storybook/vue3'
3
+ import type { Meta, StoryObj } from '@storybook/vue3-vite'
4
4
 
5
5
  import CpRadio from '@/components/CpRadio.vue'
6
6
 
7
+ const radioColors = ['accent', 'blue'] as const
8
+
7
9
  const meta = {
8
- title: 'Form/CpRadio',
10
+ title: 'Atoms/CpRadio',
9
11
  component: CpRadio,
10
12
  argTypes: {
11
13
  modelValue: {
@@ -22,7 +24,7 @@ const meta = {
22
24
  },
23
25
  color: {
24
26
  control: 'select',
25
- options: ['accent', 'blue'],
27
+ options: radioColors,
26
28
  description: 'Color variant of the radio',
27
29
  },
28
30
  autofocus: {
@@ -41,6 +43,23 @@ const sampleOptions = [
41
43
  { value: 'option3', label: 'Option 3' },
42
44
  ]
43
45
 
46
+ const wrappedRender = (args: { modelValue?: string }) => ({
47
+ components: { CpRadio },
48
+ setup() {
49
+ const value = ref(args.modelValue)
50
+ return { args, value }
51
+ },
52
+ template: `
53
+ <div style="min-width: 400px; padding: 20px;">
54
+ <CpRadio v-model="value" v-bind="args" />
55
+ </div>
56
+ `,
57
+ })
58
+
59
+ /**
60
+ * Default radio group with three plain options. Use the controls to
61
+ * experiment with each prop in isolation.
62
+ */
44
63
  export const Default: Story = {
45
64
  args: {
46
65
  modelValue: 'option1',
@@ -49,23 +68,13 @@ export const Default: Story = {
49
68
  color: 'accent',
50
69
  autofocus: false,
51
70
  },
52
- render: (args) => ({
53
- components: { CpRadio },
54
- setup() {
55
- const value = ref(args.modelValue)
56
- return { args, value }
57
- },
58
- template: `
59
- <div style="min-width: 400px; padding: 20px;">
60
- <CpRadio
61
- v-model="value"
62
- v-bind="args"
63
- />
64
- </div>
65
- `,
66
- }),
71
+ render: wrappedRender,
67
72
  }
68
73
 
74
+ /**
75
+ * Each option can provide a secondary `description` displayed under the
76
+ * label — great for presenting plans or multi-line choices.
77
+ */
69
78
  export const WithDescriptions: Story = {
70
79
  args: {
71
80
  ...Default.args,
@@ -77,6 +86,10 @@ export const WithDescriptions: Story = {
77
86
  },
78
87
  }
79
88
 
89
+ /**
90
+ * Append a right-aligned piece of information through `additionalData`
91
+ * (e.g. price, unit, shortcut).
92
+ */
80
93
  export const WithAdditionalData: Story = {
81
94
  args: {
82
95
  ...Default.args,
@@ -88,7 +101,11 @@ export const WithAdditionalData: Story = {
88
101
  },
89
102
  }
90
103
 
91
- export const WithDisabledOptions: Story = {
104
+ /**
105
+ * Disable individual options using their `disabled` flag — the value stays
106
+ * selectable on other rows.
107
+ */
108
+ export const WithDisabledOption: Story = {
92
109
  args: {
93
110
  ...Default.args,
94
111
  options: [
@@ -97,23 +114,13 @@ export const WithDisabledOptions: Story = {
97
114
  { value: 'option3', label: 'Option 3' },
98
115
  ],
99
116
  },
100
- render: (args) => ({
101
- components: { CpRadio },
102
- setup() {
103
- const value = ref(args.modelValue)
104
- return { args, value }
105
- },
106
- template: `
107
- <div style="min-width: 400px; padding: 20px;">
108
- <CpRadio
109
- v-model="value"
110
- v-bind="args"
111
- />
112
- </div>
113
- `,
114
- }),
117
+ render: wrappedRender,
115
118
  }
116
119
 
120
+ /**
121
+ * A disabled option can still be the current value — useful when the user
122
+ * cannot change a pre-selected choice.
123
+ */
117
124
  export const CheckedDisabled: Story = {
118
125
  args: {
119
126
  ...Default.args,
@@ -124,23 +131,12 @@ export const CheckedDisabled: Story = {
124
131
  ],
125
132
  modelValue: 'option1',
126
133
  },
127
- render: (args) => ({
128
- components: { CpRadio },
129
- setup() {
130
- const value = ref(args.modelValue)
131
- return { args, value }
132
- },
133
- template: `
134
- <div style="min-width: 400px; padding: 20px;">
135
- <CpRadio
136
- v-model="value"
137
- v-bind="args"
138
- />
139
- </div>
140
- `,
141
- }),
134
+ render: wrappedRender,
142
135
  }
143
136
 
137
+ /**
138
+ * Combine `description` and `additionalData` for rich option rows.
139
+ */
144
140
  export const ComplexOptions: Story = {
145
141
  args: {
146
142
  ...Default.args,
@@ -1,11 +1,14 @@
1
1
  import { ref } from 'vue'
2
2
 
3
- import type { Meta, StoryObj } from '@storybook/vue3'
3
+ import type { Meta, StoryObj } from '@storybook/vue3-vite'
4
4
 
5
5
  import CpRadioGroup from '@/components/CpRadioGroup.vue'
6
6
 
7
+ const radioGroupSizes = ['md', 'lg'] as const
8
+ const radioGroupDirections = ['vertical', 'horizontal'] as const
9
+
7
10
  const meta = {
8
- title: 'Form/CpRadioGroup',
11
+ title: 'Molecules/CpRadioGroup',
9
12
  component: CpRadioGroup,
10
13
  argTypes: {
11
14
  modelValue: {
@@ -26,7 +29,7 @@ const meta = {
26
29
  },
27
30
  direction: {
28
31
  control: 'select',
29
- options: ['vertical', 'horizontal'],
32
+ options: radioGroupDirections,
30
33
  description: 'Stack options vertically or place them in a row',
31
34
  },
32
35
  groupLabel: {
@@ -43,7 +46,7 @@ const meta = {
43
46
  },
44
47
  size: {
45
48
  control: 'select',
46
- options: ['md', 'lg'],
49
+ options: radioGroupSizes,
47
50
  description: 'The size of the radio',
48
51
  },
49
52
  },
@@ -58,6 +61,23 @@ const sampleOptions = [
58
61
  { value: 'option3', label: 'Option 3' },
59
62
  ]
60
63
 
64
+ const wrappedRender = (args: { modelValue?: string }) => ({
65
+ components: { CpRadioGroup },
66
+ setup() {
67
+ const value = ref(args.modelValue)
68
+ return { args, value }
69
+ },
70
+ template: `
71
+ <div style="min-width: 800px; padding: 20px;">
72
+ <CpRadioGroup v-model="value" v-bind="args" />
73
+ </div>
74
+ `,
75
+ })
76
+
77
+ /**
78
+ * Default radio group, stacked vertically. Use the controls to experiment
79
+ * with each prop in isolation.
80
+ */
61
81
  export const Default: Story = {
62
82
  args: {
63
83
  modelValue: 'option1',
@@ -78,16 +98,16 @@ export const Default: Story = {
78
98
  },
79
99
  template: `
80
100
  <div style="min-width: 800px; padding: 20px;">
81
- <CpRadioGroup
82
- v-model="value"
83
- v-bind="args"
84
- />
85
- <p style="margin-top: 24px;font-size:12px;">modelValue: <code>{{ value }}</code></p>
101
+ <CpRadioGroup v-model="value" v-bind="args" />
102
+ <p style="margin-top: 24px; font-size: 12px;">modelValue: <code>{{ value }}</code></p>
86
103
  </div>
87
104
  `,
88
105
  }),
89
106
  }
90
107
 
108
+ /**
109
+ * Arrange the options on a single row with `direction="horizontal"`.
110
+ */
91
111
  export const Horizontal: Story = {
92
112
  args: {
93
113
  ...Default.args,
@@ -95,6 +115,10 @@ export const Horizontal: Story = {
95
115
  },
96
116
  }
97
117
 
118
+ /**
119
+ * Add a visible label and helper text describing the whole group. Setting
120
+ * `required` puts the asterisk on the group label.
121
+ */
98
122
  export const WithGroupLabel: Story = {
99
123
  args: {
100
124
  ...Default.args,
@@ -104,6 +128,10 @@ export const WithGroupLabel: Story = {
104
128
  },
105
129
  }
106
130
 
131
+ /**
132
+ * Attach a `helperText` to individual options — useful for short
133
+ * explanations next to each choice.
134
+ */
107
135
  export const WithHelperText: Story = {
108
136
  args: {
109
137
  ...Default.args,
@@ -115,7 +143,10 @@ export const WithHelperText: Story = {
115
143
  },
116
144
  }
117
145
 
118
- export const WithDisabledOptions: Story = {
146
+ /**
147
+ * Disable individual options; the rest of the group stays selectable.
148
+ */
149
+ export const WithDisabledOption: Story = {
119
150
  args: {
120
151
  ...Default.args,
121
152
  options: [
@@ -124,23 +155,13 @@ export const WithDisabledOptions: Story = {
124
155
  { value: 'option3', label: 'Option 3' },
125
156
  ],
126
157
  },
127
- render: (args) => ({
128
- components: { CpRadioGroup },
129
- setup() {
130
- const value = ref(args.modelValue)
131
- return { args, value }
132
- },
133
- template: `
134
- <div style="min-width: 800px; padding: 20px;">
135
- <CpRadioGroup
136
- v-model="value"
137
- v-bind="args"
138
- />
139
- </div>
140
- `,
141
- }),
158
+ render: wrappedRender,
142
159
  }
143
160
 
161
+ /**
162
+ * A disabled option can still be the current value. Use this pattern for
163
+ * read-only pre-selections.
164
+ */
144
165
  export const CheckedDisabled: Story = {
145
166
  args: {
146
167
  ...Default.args,
@@ -151,19 +172,5 @@ export const CheckedDisabled: Story = {
151
172
  ],
152
173
  modelValue: 'option1',
153
174
  },
154
- render: (args) => ({
155
- components: { CpRadioGroup },
156
- setup() {
157
- const value = ref(args.modelValue)
158
- return { args, value }
159
- },
160
- template: `
161
- <div style="min-width: 800px; padding: 20px;">
162
- <CpRadioGroup
163
- v-model="value"
164
- v-bind="args"
165
- />
166
- </div>
167
- `,
168
- }),
175
+ render: wrappedRender,
169
176
  }
@@ -1,12 +1,18 @@
1
1
  import { ref } from 'vue'
2
2
 
3
- import type { Meta, StoryObj } from '@storybook/vue3'
3
+ import type { Meta, StoryObj } from '@storybook/vue3-vite'
4
4
 
5
5
  import CpInput from '@/components/CpInput.vue'
6
6
  import CpSelect from '@/components/CpSelect.vue'
7
7
 
8
+ import { docCellStyle, docLabelStyle, docRowColumnStyle } from '@/stories/documentationStyles'
9
+
10
+ const selectSizes = ['sm', 'md', 'lg'] as const
11
+
12
+ const selectStackStyle = `${docCellStyle} width: 100%; max-width: 360px;`
13
+
8
14
  const meta = {
9
- title: 'Form/CpSelect',
15
+ title: 'Molecules/CpSelect',
10
16
  component: CpSelect,
11
17
  argTypes: {
12
18
  modelValue: {
@@ -47,7 +53,7 @@ const meta = {
47
53
  },
48
54
  size: {
49
55
  control: 'select',
50
- options: ['sm', 'md', 'lg'],
56
+ options: selectSizes,
51
57
  description: 'The size of the select',
52
58
  },
53
59
  autocomplete: {
@@ -70,6 +76,7 @@ const meta = {
70
76
  } satisfies Meta<typeof CpSelect>
71
77
 
72
78
  export default meta
79
+
73
80
  type Story = StoryObj<typeof meta>
74
81
 
75
82
  const sampleOptions = [
@@ -79,6 +86,9 @@ const sampleOptions = [
79
86
  { value: '4', label: 'Option 4' },
80
87
  ]
81
88
 
89
+ /**
90
+ * Default select. Use the controls to experiment with each prop in isolation.
91
+ */
82
92
  export const Default: Story = {
83
93
  args: {
84
94
  label: 'Select Label',
@@ -101,51 +111,111 @@ export const Default: Story = {
101
111
  },
102
112
  template: `
103
113
  <div style="max-width: 400px; padding: 20px;">
104
- <CpSelect
105
- v-model="value"
106
- v-bind="args"
107
- />
114
+ <CpSelect v-model="value" v-bind="args" />
108
115
  </div>
109
116
  `,
110
117
  }),
111
118
  }
112
119
 
113
- export const WithError: Story = {
114
- args: {
115
- ...Default.args,
116
- isInvalid: true,
117
- errorMessage: 'This field is required',
118
- },
119
- }
120
+ /* -------------------------------------------------------------------------- */
121
+ /* Sizes */
122
+ /* -------------------------------------------------------------------------- */
120
123
 
121
- export const Required: Story = {
122
- args: {
123
- ...Default.args,
124
- required: true,
124
+ /**
125
+ * All sizes rendered side by side, from `sm` to `lg`.
126
+ */
127
+ export const Sizes: Story = {
128
+ parameters: {
129
+ controls: {
130
+ disable: true,
131
+ },
125
132
  },
126
- }
127
-
128
- export const Disabled: Story = {
129
133
  args: {
130
134
  ...Default.args,
131
- disabled: true,
132
135
  },
136
+ render: () => ({
137
+ components: { CpSelect },
138
+ setup() {
139
+ const value = ref('3')
140
+ return { value, sampleOptions, selectSizes, docRowColumnStyle, selectStackStyle, docLabelStyle }
141
+ },
142
+ template: `
143
+ <div :style="docRowColumnStyle">
144
+ <div v-for="size in selectSizes" :key="size" :style="selectStackStyle">
145
+ <span :style="docLabelStyle">{{ size }}</span>
146
+ <CpSelect
147
+ v-model="value"
148
+ :size="size"
149
+ label="Select label"
150
+ :options="sampleOptions"
151
+ name="select-field"
152
+ />
153
+ </div>
154
+ </div>
155
+ `,
156
+ }),
133
157
  }
134
158
 
135
- export const Small: Story = {
136
- args: {
137
- ...Default.args,
138
- size: 'sm',
139
- },
140
- }
159
+ /* -------------------------------------------------------------------------- */
160
+ /* States */
161
+ /* -------------------------------------------------------------------------- */
141
162
 
142
- export const Large: Story = {
163
+ /**
164
+ * Default, required, disabled and invalid states compared side by side.
165
+ */
166
+ export const States: Story = {
167
+ parameters: {
168
+ controls: {
169
+ disable: true,
170
+ },
171
+ },
143
172
  args: {
144
173
  ...Default.args,
145
- size: 'lg',
146
174
  },
175
+ render: () => ({
176
+ components: { CpSelect },
177
+ setup() {
178
+ const value = ref('3')
179
+ return { value, sampleOptions, docRowColumnStyle, selectStackStyle, docLabelStyle }
180
+ },
181
+ template: `
182
+ <div :style="docRowColumnStyle">
183
+ <div :style="selectStackStyle">
184
+ <span :style="docLabelStyle">Default</span>
185
+ <CpSelect v-model="value" label="Select label" :options="sampleOptions" name="s-default" />
186
+ </div>
187
+ <div :style="selectStackStyle">
188
+ <span :style="docLabelStyle">Required</span>
189
+ <CpSelect v-model="value" label="Select label" :options="sampleOptions" :required="true" name="s-required" />
190
+ </div>
191
+ <div :style="selectStackStyle">
192
+ <span :style="docLabelStyle">Disabled</span>
193
+ <CpSelect v-model="value" label="Select label" :options="sampleOptions" :disabled="true" name="s-disabled" />
194
+ </div>
195
+ <div :style="selectStackStyle">
196
+ <span :style="docLabelStyle">Invalid</span>
197
+ <CpSelect
198
+ v-model="value"
199
+ label="Select label"
200
+ :options="sampleOptions"
201
+ :is-invalid="true"
202
+ error-message="This field is required"
203
+ name="s-invalid"
204
+ />
205
+ </div>
206
+ </div>
207
+ `,
208
+ }),
147
209
  }
148
210
 
211
+ /* -------------------------------------------------------------------------- */
212
+ /* Misc */
213
+ /* -------------------------------------------------------------------------- */
214
+
215
+ /**
216
+ * Hides the default "Select an option" entry. Use this when an option must
217
+ * always be picked.
218
+ */
149
219
  export const WithoutDefaultOption: Story = {
150
220
  args: {
151
221
  ...Default.args,
@@ -153,6 +223,9 @@ export const WithoutDefaultOption: Story = {
153
223
  },
154
224
  }
155
225
 
226
+ /**
227
+ * Long option labels are truncated with an ellipsis.
228
+ */
156
229
  export const WithLongOptions: Story = {
157
230
  args: {
158
231
  ...Default.args,
@@ -165,6 +238,10 @@ export const WithLongOptions: Story = {
165
238
  },
166
239
  }
167
240
 
241
+ /**
242
+ * Combines a select and an input on the same line — for example a currency
243
+ * and an amount.
244
+ */
168
245
  export const NextToInput: Story = {
169
246
  args: {
170
247
  ...Default.args,
@@ -180,10 +257,7 @@ export const NextToInput: Story = {
180
257
  },
181
258
  template: `
182
259
  <div style="display: flex; flex-wrap: wrap; align-items: center; gap: 10px; max-width: 400px; padding: 20px;">
183
- <CpSelect
184
- v-model="value"
185
- v-bind="args"
186
- />
260
+ <CpSelect v-model="value" v-bind="args" />
187
261
  <CpInput :size="args.size" label="Input Label" name="input-field" placeholder="Enter text here" v-model="textValue" />
188
262
  </div>
189
263
  `,