@demos-europe/demosplan-ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/buildTokens.js +59 -0
- package/components/DpButton/DpButton.stories.mdx +136 -0
- package/components/DpButton/DpButton.vue +118 -0
- package/components/DpDetails/DpDetails.stories.mdx +55 -0
- package/components/DpDetails/DpDetails.vue +58 -0
- package/components/DpIcon/DpIcon.stories.mdx +396 -0
- package/components/DpIcon/DpIcon.vue +51 -0
- package/components/DpIcon/util/iconVariables.js +148 -0
- package/components/DpInput/DpInput.stories.mdx +127 -0
- package/components/DpInput/DpInput.vue +284 -0
- package/components/DpLabel/DpLabel.stories.mdx +103 -0
- package/components/DpLabel/DpLabel.vue +112 -0
- package/components/DpLoading/DpLoading.stories.mdx +63 -0
- package/components/DpLoading/DpLoading.vue +63 -0
- package/components/core/DpAccordion.vue +108 -0
- package/components/core/DpAnonymizeText.vue +136 -0
- package/components/core/DpAutocomplete.vue +133 -0
- package/components/core/DpBulkEditHeader.vue +53 -0
- package/components/core/DpButtonIcon.vue +47 -0
- package/components/core/DpButtonRow.vue +155 -0
- package/components/core/DpCard.vue +54 -0
- package/components/core/DpChangeStateAtDate.vue +223 -0
- package/components/core/DpCheckboxGroup.vue +93 -0
- package/components/core/DpContextualHelp.vue +54 -0
- package/components/core/DpCopyPasteButton.vue +47 -0
- package/components/core/DpDashboardTaskCard.vue +123 -0
- package/components/core/DpDataTable/DataTableSearch.js +44 -0
- package/components/core/DpDataTable/DpColumnSelector.vue +133 -0
- package/components/core/DpDataTable/DpDataTable.vue +647 -0
- package/components/core/DpDataTable/DpDataTableExtended.vue +377 -0
- package/components/core/DpDataTable/DpResizeHandle.vue +37 -0
- package/components/core/DpDataTable/DpSelectPageItemCount.vue +70 -0
- package/components/core/DpDataTable/DpTableHeader.vue +197 -0
- package/components/core/DpDataTable/DpTableRow.vue +355 -0
- package/components/core/DpDataTable/DpWrapTrigger.vue +48 -0
- package/components/core/DpDataTable/lib/ResizableColumns.js +83 -0
- package/components/core/DpEditableList.vue +161 -0
- package/components/core/DpEditor/DpBoilerPlate.vue +140 -0
- package/components/core/DpEditor/DpBoilerPlateModal.vue +166 -0
- package/components/core/DpEditor/DpEditor.vue +1281 -0
- package/components/core/DpEditor/DpLinkModal.vue +117 -0
- package/components/core/DpEditor/DpRecommendationModal/DpInsertableRecommendation.vue +137 -0
- package/components/core/DpEditor/DpRecommendationModal.vue +283 -0
- package/components/core/DpEditor/DpResizableImage.vue +121 -0
- package/components/core/DpEditor/DpUploadModal.vue +121 -0
- package/components/core/DpEditor/libs/Decoration.js +66 -0
- package/components/core/DpEditor/libs/SegmentRangeChangePlugin.js +35 -0
- package/components/core/DpEditor/libs/editorAnonymize.js +66 -0
- package/components/core/DpEditor/libs/editorBuildSuggestion.js +269 -0
- package/components/core/DpEditor/libs/editorCustomDelete.js +32 -0
- package/components/core/DpEditor/libs/editorCustomImage.js +100 -0
- package/components/core/DpEditor/libs/editorCustomInsert.js +32 -0
- package/components/core/DpEditor/libs/editorCustomLink.js +46 -0
- package/components/core/DpEditor/libs/editorCustomMark.js +32 -0
- package/components/core/DpEditor/libs/editorInsertAtCursorPos.js +41 -0
- package/components/core/DpEditor/libs/editorObscure.js +60 -0
- package/components/core/DpEditor/libs/editorUnAnonymize.js +56 -0
- package/components/core/DpEditor/libs/handleWordPaste.js +360 -0
- package/components/core/DpEditor/libs/preventDrop.js +31 -0
- package/components/core/DpEditor/libs/preventKeyboardInput.js +27 -0
- package/components/core/DpEditor/libs/preventPaste.js +28 -0
- package/components/core/DpFlyout.vue +119 -0
- package/components/core/DpInlineNotification.vue +116 -0
- package/components/core/DpModal.vue +208 -0
- package/components/core/DpObscure.vue +29 -0
- package/components/core/DpPager.vue +139 -0
- package/components/core/DpProgressBar.vue +67 -0
- package/components/core/DpRegisterFlyout.vue +58 -0
- package/components/core/DpResettableInput.vue +140 -0
- package/components/core/DpSkeletonBox.vue +32 -0
- package/components/core/DpSlidebar.vue +86 -0
- package/components/core/DpSlidingPagination.vue +45 -0
- package/components/core/DpSplitButton.vue +77 -0
- package/components/core/DpSwitcher.vue +62 -0
- package/components/core/DpTableCardList/DpTableCard.vue +61 -0
- package/components/core/DpTableCardList/DpTableCardListHeader.vue +83 -0
- package/components/core/DpTabs/DpTab.vue +52 -0
- package/components/core/DpTabs/DpTabs.vue +165 -0
- package/components/core/DpTextWrapper.vue +65 -0
- package/components/core/DpToggleForm.vue +72 -0
- package/components/core/DpTooltipIcon.vue +52 -0
- package/components/core/DpTransitionExpand.vue +87 -0
- package/components/core/DpTreeList/DpTreeList.vue +334 -0
- package/components/core/DpTreeList/DpTreeListCheckbox.vue +79 -0
- package/components/core/DpTreeList/DpTreeListNode.vue +348 -0
- package/components/core/DpTreeList/DpTreeListToggle.vue +71 -0
- package/components/core/DpTreeList/utils/constants.js +14 -0
- package/components/core/DpUpload/DpUpload.vue +223 -0
- package/components/core/DpUpload/DpUploadFiles.vue +269 -0
- package/components/core/DpUpload/DpUploadedFile.vue +80 -0
- package/components/core/DpUpload/DpUploadedFileList.vue +56 -0
- package/components/core/DpUpload/utils/GetFileIdsByHash.js +42 -0
- package/components/core/DpUpload/utils/UppyTranslations.js +31 -0
- package/components/core/DpVideoPlayer.vue +115 -0
- package/components/core/HeightLimit.vue +121 -0
- package/components/core/MultistepNav.vue +89 -0
- package/components/core/form/DpCheckbox.vue +108 -0
- package/components/core/form/DpDateRangePicker.vue +186 -0
- package/components/core/form/DpDatepicker.vue +160 -0
- package/components/core/form/DpDatetimePicker.vue +194 -0
- package/components/core/form/DpFormRow.vue +79 -0
- package/components/core/form/DpMultiselect.vue +164 -0
- package/components/core/form/DpRadio.vue +128 -0
- package/components/core/form/DpSearchField.vue +110 -0
- package/components/core/form/DpSelect.vue +149 -0
- package/components/core/form/DpTextArea.vue +152 -0
- package/components/core/form/DpTimePicker.vue +374 -0
- package/components/core/form/DpToggle.vue +78 -0
- package/components/core/index.js +132 -0
- package/components/core/notify/DpNotifyContainer.vue +122 -0
- package/components/core/notify/DpNotifyMessage.vue +95 -0
- package/components/core/shared/DpStickyElement.vue +95 -0
- package/components/index.js +24 -0
- package/components/shared/translations.js +15 -0
- package/directives/CleanHtml/CleanHtml.js +50 -0
- package/directives/CleanHtml/CleanHtml.stories.mdx +64 -0
- package/directives/Tooltip/Tooltip.js +40 -0
- package/directives/Tooltip/Tooltip.stories.mdx +42 -0
- package/directives/index.js +17 -0
- package/lib/index.js +14 -0
- package/lib/prefixClass.js +47 -0
- package/mixins/index.js +14 -0
- package/mixins/prefixClassMixin.js +22 -0
- package/package.json +52 -0
- package/shared/props.js +86 -0
- package/style/index.css +7 -0
- package/tailwind.config.js +24 -0
- package/tokens/color.json +358 -0
- package/tokens/color.stories.mdx +45 -0
- package/tokens/fontSize.json +100 -0
- package/tokens/space.json +33 -0
- package/utils/lengthHint.js +69 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { Canvas, Meta, Story } from '@storybook/addon-docs'
|
|
2
|
+
import DpInput from './DpInput'
|
|
3
|
+
|
|
4
|
+
<Meta
|
|
5
|
+
title="Components/Input"
|
|
6
|
+
component={DpInput}
|
|
7
|
+
argTypes={{
|
|
8
|
+
maxlength: {
|
|
9
|
+
control: {
|
|
10
|
+
type: 'number'
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}} />
|
|
14
|
+
|
|
15
|
+
# Input
|
|
16
|
+
|
|
17
|
+
The `DpInput` component is used for the following form input fields:
|
|
18
|
+
- text
|
|
19
|
+
- email
|
|
20
|
+
- number
|
|
21
|
+
- password
|
|
22
|
+
- tel
|
|
23
|
+
|
|
24
|
+
export const Template = (args, { argTypes }) => ({
|
|
25
|
+
props: Object.keys(argTypes),
|
|
26
|
+
components: { DpInput },
|
|
27
|
+
template: `<dp-input v-bind="$props" />`
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
|
|
32
|
+
### Text input
|
|
33
|
+
|
|
34
|
+
<Canvas>
|
|
35
|
+
<Story
|
|
36
|
+
name="Text input"
|
|
37
|
+
args={{
|
|
38
|
+
id: 'someId',
|
|
39
|
+
label: {
|
|
40
|
+
text: 'First name'
|
|
41
|
+
},
|
|
42
|
+
width: 'u-1-of-2'
|
|
43
|
+
}}>
|
|
44
|
+
{Template.bind({})}
|
|
45
|
+
</Story>
|
|
46
|
+
</Canvas>
|
|
47
|
+
|
|
48
|
+
### Hint
|
|
49
|
+
|
|
50
|
+
The `hint` property adds the provided string between label and input field.
|
|
51
|
+
|
|
52
|
+
<Canvas>
|
|
53
|
+
<Story
|
|
54
|
+
name="Hint"
|
|
55
|
+
args={{
|
|
56
|
+
id: 'someId',
|
|
57
|
+
label: {
|
|
58
|
+
hint: 'This is a hint that explains what to enter in the input',
|
|
59
|
+
text: 'Contact person'
|
|
60
|
+
},
|
|
61
|
+
width: 'u-1-of-2'
|
|
62
|
+
}}>
|
|
63
|
+
{Template.bind({})}
|
|
64
|
+
</Story>
|
|
65
|
+
</Canvas>
|
|
66
|
+
|
|
67
|
+
### Required
|
|
68
|
+
|
|
69
|
+
If an input field is `required`, an asterisk will be added to its label.
|
|
70
|
+
|
|
71
|
+
<Canvas>
|
|
72
|
+
<Story
|
|
73
|
+
name="Required"
|
|
74
|
+
args={{
|
|
75
|
+
id: 'someId',
|
|
76
|
+
label: {
|
|
77
|
+
text: 'Phone'
|
|
78
|
+
},
|
|
79
|
+
pattern: '^(\+?)(-| |[0-9]|\(|\))*$',
|
|
80
|
+
required: true,
|
|
81
|
+
type: 'tel',
|
|
82
|
+
width: 'u-1-of-4'
|
|
83
|
+
}}>
|
|
84
|
+
{Template.bind({})}
|
|
85
|
+
</Story>
|
|
86
|
+
</Canvas>
|
|
87
|
+
|
|
88
|
+
### Disabled
|
|
89
|
+
|
|
90
|
+
<Canvas>
|
|
91
|
+
<Story
|
|
92
|
+
name="Disabled"
|
|
93
|
+
args={{
|
|
94
|
+
disabled: true,
|
|
95
|
+
id: 'someId',
|
|
96
|
+
label: {
|
|
97
|
+
text: 'Email address'
|
|
98
|
+
},
|
|
99
|
+
pattern: '^(\+?)(-| |[0-9]|\(|\))*$',
|
|
100
|
+
type: 'email',
|
|
101
|
+
value: 'yourEmail@example.com',
|
|
102
|
+
width: 'u-1-of-4'
|
|
103
|
+
}}>
|
|
104
|
+
{Template.bind({})}
|
|
105
|
+
</Story>
|
|
106
|
+
</Canvas>
|
|
107
|
+
|
|
108
|
+
### Tooltip
|
|
109
|
+
|
|
110
|
+
The `tooltip` property adds a contextual help icon that reveals additional information on the input field when the user hovers
|
|
111
|
+
over it with their mouse. It should be used sparingly and only to reveal non-critical information, whereas critical information should be presented immediately.
|
|
112
|
+
|
|
113
|
+
<Canvas>
|
|
114
|
+
<Story
|
|
115
|
+
name="Tooltip"
|
|
116
|
+
args={{
|
|
117
|
+
id: 'someId',
|
|
118
|
+
label: {
|
|
119
|
+
text: 'Last name',
|
|
120
|
+
tooltip: 'This is a text adding some more information on the input field'
|
|
121
|
+
},
|
|
122
|
+
type: 'text',
|
|
123
|
+
width: 'u-1-of-4'
|
|
124
|
+
}}>
|
|
125
|
+
{Template.bind({})}
|
|
126
|
+
</Story>
|
|
127
|
+
</Canvas>
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
<license>
|
|
2
|
+
(c) 2010-present DEMOS E-Partizipation GmbH.
|
|
3
|
+
|
|
4
|
+
This file is part of the package @demos-europe/demosplan-ui,
|
|
5
|
+
for more information see the license file.
|
|
6
|
+
|
|
7
|
+
All rights reserved
|
|
8
|
+
</license>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<div :class="containerWidth !== '' ? prefixClass(containerWidth) : false">
|
|
12
|
+
<dp-label
|
|
13
|
+
v-if="label.text !== ''"
|
|
14
|
+
v-bind="{
|
|
15
|
+
...label,
|
|
16
|
+
for: id,
|
|
17
|
+
hint: labelHint,
|
|
18
|
+
required: required
|
|
19
|
+
}" /><!--
|
|
20
|
+
--><input
|
|
21
|
+
:id="id"
|
|
22
|
+
:name="name !== '' ? name : false"
|
|
23
|
+
:class="prefixClass(classes)"
|
|
24
|
+
:data-counter="dataCounter !== '' ? dataCounter : false"
|
|
25
|
+
:data-dp-validate-error="dataDpValidateError || false"
|
|
26
|
+
:data-dp-validate-if="dataDpValidateIf !== '' ? dataDpValidateIf : false"
|
|
27
|
+
:data-dp-validate-should-equal="dataDpValidateShouldEqual !== '' ? dataDpValidateShouldEqual : false"
|
|
28
|
+
:data-cy="dataCy !== '' ? dataCy : false"
|
|
29
|
+
:aria-labelledby="ariaLabelledby"
|
|
30
|
+
:maxlength="maxlength !== '' ? maxlength : false"
|
|
31
|
+
:minlength="minlength !== '' ? minlength : false"
|
|
32
|
+
:type="type"
|
|
33
|
+
:pattern="pattern !== '' ? pattern : false"
|
|
34
|
+
:placeholder="placeholder !== '' ? placeholder : false"
|
|
35
|
+
:disabled="disabled"
|
|
36
|
+
:readonly="readonly"
|
|
37
|
+
:required="required"
|
|
38
|
+
:autocomplete="autocomplete !== '' ? autocomplete : false"
|
|
39
|
+
:size="size ? size : false"
|
|
40
|
+
v-model="currentValue"
|
|
41
|
+
@focus="$emit('focus')"
|
|
42
|
+
@input="$emit('input', currentValue)"
|
|
43
|
+
@keydown.enter="handleEnter">
|
|
44
|
+
</div>
|
|
45
|
+
</template>
|
|
46
|
+
|
|
47
|
+
<script>
|
|
48
|
+
import { exactlengthHint, maxlengthHint, minlengthHint } from '../../utils/lengthHint'
|
|
49
|
+
import DpLabel from '../DpLabel/DpLabel'
|
|
50
|
+
import { length } from '../../shared/props'
|
|
51
|
+
import { prefixClassMixin } from '../../mixins'
|
|
52
|
+
|
|
53
|
+
export default {
|
|
54
|
+
name: 'DpInput',
|
|
55
|
+
|
|
56
|
+
components: {
|
|
57
|
+
DpLabel
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
mixins: [prefixClassMixin],
|
|
61
|
+
|
|
62
|
+
props: {
|
|
63
|
+
/**
|
|
64
|
+
* Reference another element on the page to define an accessible name if there is no label or
|
|
65
|
+
* you want to override the label.
|
|
66
|
+
*/
|
|
67
|
+
ariaLabelledby: {
|
|
68
|
+
type: [String, Boolean],
|
|
69
|
+
required: false,
|
|
70
|
+
default: false
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Tell the browser if autocomplete is allowed or not. If enabled the browser is allowed
|
|
75
|
+
* to automatically complete the input. You can also provide a type of data which is expected.
|
|
76
|
+
*/
|
|
77
|
+
autocomplete: {
|
|
78
|
+
type: String,
|
|
79
|
+
required: false,
|
|
80
|
+
default: ''
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
dataCounter: {
|
|
84
|
+
type: String,
|
|
85
|
+
required: false,
|
|
86
|
+
default: ''
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
dataCy: {
|
|
90
|
+
type: String,
|
|
91
|
+
required: false,
|
|
92
|
+
default: ''
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
dataDpValidateError: {
|
|
96
|
+
type: String,
|
|
97
|
+
required: false,
|
|
98
|
+
default: ''
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
dataDpValidateIf: {
|
|
102
|
+
type: String,
|
|
103
|
+
required: false,
|
|
104
|
+
default: ''
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
dataDpValidateShouldEqual: {
|
|
108
|
+
type: String,
|
|
109
|
+
required: false,
|
|
110
|
+
default: ''
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
disabled: {
|
|
114
|
+
type: Boolean,
|
|
115
|
+
required: false,
|
|
116
|
+
default: false
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Use: when input field used with Icon || Button, then input field has padding right.
|
|
121
|
+
*/
|
|
122
|
+
hasIcon: {
|
|
123
|
+
type: Boolean,
|
|
124
|
+
required: false,
|
|
125
|
+
default: false
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
id: {
|
|
129
|
+
type: String,
|
|
130
|
+
required: true
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
label: {
|
|
134
|
+
type: Object,
|
|
135
|
+
default: () => ({
|
|
136
|
+
bold: true,
|
|
137
|
+
hint: '',
|
|
138
|
+
text: '',
|
|
139
|
+
tooltip: ''
|
|
140
|
+
}),
|
|
141
|
+
validator: (prop) => {
|
|
142
|
+
return Object.keys(prop).every(key => ['bold', 'hint', 'text', 'tooltip'].includes(key))
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Limit the maximum allowed number of characters to the given amount.
|
|
148
|
+
*/
|
|
149
|
+
maxlength: length,
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Define the minimum number of characters that need to be given.
|
|
153
|
+
*/
|
|
154
|
+
minlength: length,
|
|
155
|
+
|
|
156
|
+
name: {
|
|
157
|
+
type: String,
|
|
158
|
+
required: false,
|
|
159
|
+
default: ''
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
pattern: {
|
|
163
|
+
type: String,
|
|
164
|
+
required: false,
|
|
165
|
+
default: ''
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
placeholder: {
|
|
169
|
+
type: String,
|
|
170
|
+
required: false,
|
|
171
|
+
default: ''
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Set to false to prevent default behavior onEnter.
|
|
176
|
+
*/
|
|
177
|
+
preventDefaultOnEnter: {
|
|
178
|
+
type: Boolean,
|
|
179
|
+
required: false,
|
|
180
|
+
default: true
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
readonly: {
|
|
184
|
+
type: Boolean,
|
|
185
|
+
required: false,
|
|
186
|
+
default: false
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
required: {
|
|
190
|
+
type: Boolean,
|
|
191
|
+
required: false,
|
|
192
|
+
default: false
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* When setting a number for the `size` prop, this is directly rendered
|
|
197
|
+
* as html attribute on the input element. Also, it is assumed that visual sizing
|
|
198
|
+
* based on that value shall be applied, that is why both container classes
|
|
199
|
+
* and element classes do not define any width styles when a size is set here.
|
|
200
|
+
*/
|
|
201
|
+
size: {
|
|
202
|
+
type: Number,
|
|
203
|
+
required: false,
|
|
204
|
+
default: undefined
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
type: {
|
|
208
|
+
type: String,
|
|
209
|
+
required: false,
|
|
210
|
+
default: 'text'
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
value: {
|
|
214
|
+
type: String,
|
|
215
|
+
required: false,
|
|
216
|
+
default: ''
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Full width by default; set to 'auto' to have no width defined.
|
|
221
|
+
* @deprecated Apply width to the parent element of DpInput.
|
|
222
|
+
*/
|
|
223
|
+
width: {
|
|
224
|
+
type: String,
|
|
225
|
+
default: 'u-1-of-1'
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
data () {
|
|
230
|
+
return {
|
|
231
|
+
currentValue: this.value
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
computed: {
|
|
236
|
+
classes () {
|
|
237
|
+
let cssClasses = []
|
|
238
|
+
cssClasses = (this.size > 0) ? [] : [...cssClasses, 'u-1-of-1']
|
|
239
|
+
cssClasses = this.readonly || this.disabled ? [...cssClasses, 'bg-color--grey-light-2'] : cssClasses
|
|
240
|
+
cssClasses = this.type !== 'search' ? [...cssClasses, 'o-form__control-input'] : [...cssClasses, 'o-form__control-search']
|
|
241
|
+
cssClasses = this.hasIcon ? [...cssClasses, 'u-pr'] : cssClasses
|
|
242
|
+
return cssClasses.join(' ')
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
containerWidth () {
|
|
246
|
+
return (this.width === 'auto' || this.size > 0) ? '' : this.width
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
labelHint () {
|
|
250
|
+
const hint = typeof this.label.hint !== 'undefined' && this.label.hint !== '' ? [this.label.hint] : []
|
|
251
|
+
|
|
252
|
+
if (this.maxlength && !this.minlength) {
|
|
253
|
+
hint.push(maxlengthHint(this.currentValue.length, this.maxlength))
|
|
254
|
+
} else if (this.minlength && !this.maxlength) {
|
|
255
|
+
hint.push(minlengthHint(this.currentValue.length, this.minlength))
|
|
256
|
+
} else if (this.maxlength && this.minlength) {
|
|
257
|
+
if (this.maxlength === this.minlength) {
|
|
258
|
+
hint.push(exactlengthHint(this.currentValue.length, this.maxlength))
|
|
259
|
+
} else {
|
|
260
|
+
hint.push(maxlengthHint(this.currentValue.length, this.maxlength))
|
|
261
|
+
hint.push(minlengthHint(this.currentValue.length, this.minlength))
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return hint
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
watch: {
|
|
270
|
+
value: function () {
|
|
271
|
+
this.currentValue = this.value
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
methods: {
|
|
276
|
+
handleEnter (event) {
|
|
277
|
+
if (this.preventDefaultOnEnter === true) {
|
|
278
|
+
event.preventDefault()
|
|
279
|
+
}
|
|
280
|
+
this.$emit('enter')
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
</script>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Canvas, Meta, Story } from '@storybook/addon-docs'
|
|
2
|
+
import DpLabel from './DpLabel'
|
|
3
|
+
|
|
4
|
+
<Meta
|
|
5
|
+
title="Components/Label"
|
|
6
|
+
component={DpLabel} />
|
|
7
|
+
|
|
8
|
+
# Label
|
|
9
|
+
|
|
10
|
+
The `DpLabel` component is used to add a label to form controls.
|
|
11
|
+
|
|
12
|
+
It is included in the following <strong><i>demosplan-ui</i></strong> form components:
|
|
13
|
+
|
|
14
|
+
- DpCheckbox
|
|
15
|
+
- DpInput
|
|
16
|
+
- DpRadio
|
|
17
|
+
- DpSelect
|
|
18
|
+
- DpDateTimePicker
|
|
19
|
+
- DpTextarea
|
|
20
|
+
- DpTimePicker
|
|
21
|
+
|
|
22
|
+
If you want to use any of these components, you don't need to import `DpLabel` separately.
|
|
23
|
+
|
|
24
|
+
`DpLabel` is currently not included in the following <strong><i>demosplan-ui</i></strong> form components:
|
|
25
|
+
|
|
26
|
+
- DpMultiselect
|
|
27
|
+
- DpTiptap
|
|
28
|
+
- DpDatepicker
|
|
29
|
+
- DpDateRangePicker
|
|
30
|
+
|
|
31
|
+
If you want to use any of these components, you need to import `DpLabel` separately.
|
|
32
|
+
|
|
33
|
+
export const Template = (args, { argTypes }) => ({
|
|
34
|
+
props: Object.keys(argTypes),
|
|
35
|
+
components: { DpLabel },
|
|
36
|
+
template: `<dp-label v-bind="$props" />`
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
## Default usage
|
|
40
|
+
|
|
41
|
+
<Canvas>
|
|
42
|
+
<Story
|
|
43
|
+
name="Default usage"
|
|
44
|
+
args={{
|
|
45
|
+
for: 'formControlId',
|
|
46
|
+
text: 'First name',
|
|
47
|
+
width: 'u-1-of-2'
|
|
48
|
+
}}>
|
|
49
|
+
{Template.bind({})}
|
|
50
|
+
</Story>
|
|
51
|
+
</Canvas>
|
|
52
|
+
|
|
53
|
+
## Required
|
|
54
|
+
|
|
55
|
+
If a form control is `required`, an asterisk will be added to the label.
|
|
56
|
+
|
|
57
|
+
<Canvas>
|
|
58
|
+
<Story
|
|
59
|
+
name="Required"
|
|
60
|
+
args={{
|
|
61
|
+
for: 'formControlId',
|
|
62
|
+
required: true,
|
|
63
|
+
text: 'E-mail address',
|
|
64
|
+
width: 'u-1-of-2'
|
|
65
|
+
}}>
|
|
66
|
+
{Template.bind({})}
|
|
67
|
+
</Story>
|
|
68
|
+
</Canvas>
|
|
69
|
+
|
|
70
|
+
## Hint
|
|
71
|
+
|
|
72
|
+
The `hint` property adds the provided string below the label.
|
|
73
|
+
|
|
74
|
+
<Canvas>
|
|
75
|
+
<Story
|
|
76
|
+
name="Hint"
|
|
77
|
+
args={{
|
|
78
|
+
for: 'formControlId',
|
|
79
|
+
hint: 'This is a hint that explains what to enter in the corresponding form control',
|
|
80
|
+
text: 'Contact person',
|
|
81
|
+
width: 'u-1-of-2'
|
|
82
|
+
}}>
|
|
83
|
+
{Template.bind({})}
|
|
84
|
+
</Story>
|
|
85
|
+
</Canvas>
|
|
86
|
+
|
|
87
|
+
## Tooltip
|
|
88
|
+
|
|
89
|
+
The `tooltip` property adds a contextual help icon that reveals additional information on the form control when the user
|
|
90
|
+
hovers over it with their mouse.
|
|
91
|
+
|
|
92
|
+
<Canvas>
|
|
93
|
+
<Story
|
|
94
|
+
name="Tooltip"
|
|
95
|
+
args={{
|
|
96
|
+
for: 'formControlId',
|
|
97
|
+
tooltip: 'This is a text adding some more information on the form control',
|
|
98
|
+
text: 'Authorized users',
|
|
99
|
+
width: 'u-1-of-2'
|
|
100
|
+
}}>
|
|
101
|
+
{Template.bind({})}
|
|
102
|
+
</Story>
|
|
103
|
+
</Canvas>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<license>
|
|
2
|
+
(c) 2010-present DEMOS E-Partizipation GmbH.
|
|
3
|
+
|
|
4
|
+
This file is part of the package @demos-europe/demosplan-ui,
|
|
5
|
+
for more information see the license file.
|
|
6
|
+
|
|
7
|
+
All rights reserved
|
|
8
|
+
</license>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<label
|
|
12
|
+
:class="prefixClass(['o-form__label flex', bold ? 'weight--bold' : 'weight--normal', hints.length > 0 ? 'has-hint' : ''])"
|
|
13
|
+
:for="labelFor">
|
|
14
|
+
<span>
|
|
15
|
+
<span v-cleanhtml="text" /><span v-if="required">*</span>
|
|
16
|
+
<span
|
|
17
|
+
v-if="hints.length > 0"
|
|
18
|
+
:class="prefixClass('display--block font-size-small weight--normal')">
|
|
19
|
+
<span
|
|
20
|
+
:class="prefixClass(['display--inline-block'])"
|
|
21
|
+
:key="i"
|
|
22
|
+
v-for="(h, i) in hints"
|
|
23
|
+
v-cleanhtml="h" />
|
|
24
|
+
</span>
|
|
25
|
+
</span>
|
|
26
|
+
<i
|
|
27
|
+
v-if="tooltip !== ''"
|
|
28
|
+
:class="prefixClass('fa fa-question-circle u-mt-0_125 flex-item-end')"
|
|
29
|
+
:aria-label="ariaLabel"
|
|
30
|
+
v-tooltip="tooltip" />
|
|
31
|
+
</label>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script>
|
|
35
|
+
import { CleanHtml } from 'demosplan-ui/directives'
|
|
36
|
+
import { de } from '../shared/translations'
|
|
37
|
+
import { prefixClassMixin } from '../../mixins'
|
|
38
|
+
|
|
39
|
+
export default {
|
|
40
|
+
name: 'DpLabel',
|
|
41
|
+
|
|
42
|
+
directives: {
|
|
43
|
+
cleanhtml: CleanHtml
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
mixins: [prefixClassMixin],
|
|
47
|
+
|
|
48
|
+
props: {
|
|
49
|
+
bold: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
required: false,
|
|
52
|
+
default: true
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
for: {
|
|
56
|
+
type: String,
|
|
57
|
+
required: true
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// Can be string or array (the second element being the "maxlength" hint).
|
|
61
|
+
hint: {
|
|
62
|
+
type: [String, Array],
|
|
63
|
+
required: false,
|
|
64
|
+
default: () => []
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
text: {
|
|
68
|
+
type: String,
|
|
69
|
+
required: true
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
tooltip: {
|
|
73
|
+
type: String,
|
|
74
|
+
required: false,
|
|
75
|
+
default: ''
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
required: {
|
|
79
|
+
type: Boolean,
|
|
80
|
+
required: false,
|
|
81
|
+
default: false
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
computed: {
|
|
86
|
+
ariaLabel () {
|
|
87
|
+
return de.contextualHelp
|
|
88
|
+
},
|
|
89
|
+
/**
|
|
90
|
+
* List of Hints
|
|
91
|
+
*
|
|
92
|
+
* @return Array{String}
|
|
93
|
+
*/
|
|
94
|
+
hints () {
|
|
95
|
+
if (this.hint) {
|
|
96
|
+
return this.wrapItemIntoArray(this.hint)
|
|
97
|
+
}
|
|
98
|
+
return []
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
labelFor () {
|
|
102
|
+
return this.for
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
methods: {
|
|
107
|
+
wrapItemIntoArray (item) {
|
|
108
|
+
return Array.isArray(item) ? item : [item]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
</script>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Canvas, Meta, Story } from '@storybook/addon-docs'
|
|
2
|
+
import { action } from '@storybook/addon-actions'
|
|
3
|
+
|
|
4
|
+
import DpLoading from './DpLoading'
|
|
5
|
+
|
|
6
|
+
<Meta
|
|
7
|
+
title="Components/Loading"
|
|
8
|
+
component={DpLoading} />
|
|
9
|
+
|
|
10
|
+
# Loading
|
|
11
|
+
|
|
12
|
+
The `DpLoading` component renders a spinning animation alongside some explanatory text.
|
|
13
|
+
|
|
14
|
+
It indicates background activity and is especially used when components load data on first page load.
|
|
15
|
+
|
|
16
|
+
export const Template = (args, { argTypes }) => ({
|
|
17
|
+
props: Object.keys(argTypes),
|
|
18
|
+
components: { DpLoading },
|
|
19
|
+
template: `<dp-loading v-bind="$props" @click="action" />`,
|
|
20
|
+
methods: {
|
|
21
|
+
action: action('click')
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
## Default usage
|
|
26
|
+
|
|
27
|
+
<Canvas>
|
|
28
|
+
<Story name="Default">
|
|
29
|
+
{Template.bind({})}
|
|
30
|
+
</Story>
|
|
31
|
+
</Canvas>
|
|
32
|
+
|
|
33
|
+
## Without label
|
|
34
|
+
|
|
35
|
+
In contexts with limited space, use the `hide-label` prop.
|
|
36
|
+
|
|
37
|
+
<Canvas>
|
|
38
|
+
<Story
|
|
39
|
+
name="hideLabel"
|
|
40
|
+
args={{
|
|
41
|
+
hideLabel: true
|
|
42
|
+
}}>
|
|
43
|
+
{Template.bind({})}
|
|
44
|
+
</Story>
|
|
45
|
+
</Canvas>
|
|
46
|
+
|
|
47
|
+
## As overlay
|
|
48
|
+
|
|
49
|
+
To block interactions with content that is being refreshed, the `overlay` prop may be used.
|
|
50
|
+
|
|
51
|
+
<Canvas withSource="open">
|
|
52
|
+
<h1>
|
|
53
|
+
Some content that is still present but covered by the loading component,
|
|
54
|
+
which makes it impossible to interact with said content.
|
|
55
|
+
</h1>
|
|
56
|
+
<Story
|
|
57
|
+
name="Overlay"
|
|
58
|
+
args={{
|
|
59
|
+
overlay: true
|
|
60
|
+
}}>
|
|
61
|
+
{Template.bind({})}
|
|
62
|
+
</Story>
|
|
63
|
+
</Canvas>
|