@digigov/react-modules 1.2.0-rc.30 → 1.2.0-rc.31
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/Faq/Faq.stories.d.ts +8 -0
- package/Faq/Results/index.js +29 -0
- package/Faq/Results/package.json +6 -0
- package/Faq/Results.d.ts +9 -0
- package/Faq/Results.js.map +7 -0
- package/Faq/__stories__/Default.d.ts +2 -0
- package/Faq/hooks/index.js +66 -0
- package/Faq/hooks/package.json +6 -0
- package/Faq/hooks.d.ts +15 -0
- package/Faq/hooks.js.map +7 -0
- package/Faq/index.d.ts +43 -0
- package/Faq/index.js +169 -0
- package/Faq/index.js.map +7 -0
- package/Faq/index.test.d.ts +1 -0
- package/Faq/package.json +6 -0
- package/Faq/slug/index.js +97 -0
- package/Faq/slug/package.json +6 -0
- package/Faq/slug.d.ts +1 -0
- package/Faq/slug.js.map +7 -0
- package/Faq/splitted.test.d.ts +1 -0
- package/Faq/utils/index.js +8 -0
- package/Faq/utils/package.json +6 -0
- package/Faq/utils.d.ts +1 -0
- package/Faq/utils.js.map +7 -0
- package/FilteredResults/__stories__/Default.d.ts +1 -1
- package/cjs/Faq/Results/index.js +58 -0
- package/cjs/Faq/Results.js.map +7 -0
- package/cjs/Faq/hooks/index.js +90 -0
- package/cjs/Faq/hooks.js.map +7 -0
- package/cjs/Faq/index.js +194 -0
- package/cjs/Faq/index.js.map +7 -0
- package/cjs/Faq/slug/index.js +120 -0
- package/cjs/Faq/slug.js.map +7 -0
- package/cjs/Faq/utils/index.js +31 -0
- package/cjs/Faq/utils.js.map +7 -0
- package/cjs/index.js +3 -1
- package/cjs/index.js.map +2 -2
- package/cjs/lazy/index.js +1 -0
- package/cjs/lazy.js.map +2 -2
- package/cjs/registry/index.js +10 -0
- package/cjs/registry.js.map +2 -2
- package/index.d.ts +1 -0
- package/index.js +2 -1
- package/index.js.map +2 -2
- package/lazy/index.js +1 -0
- package/package.json +8 -8
- package/registry/index.js +10 -0
- package/src/Faq/Faq.stories.js +7 -0
- package/src/Faq/Results.tsx +53 -0
- package/src/Faq/__stories__/Default.tsx +292 -0
- package/src/Faq/hooks.ts +89 -0
- package/src/Faq/index.test.tsx +24 -0
- package/src/Faq/index.tsx +286 -0
- package/src/Faq/slug.ts +140 -0
- package/src/Faq/splitted.test.tsx +19 -0
- package/src/Faq/utils.ts +5 -0
- package/src/FilteredResults/__stories__/Default.tsx +1 -1
- package/src/FilteredResults/index.test.tsx +4 -0
- package/src/FilteredResults/splitted.test.tsx +4 -0
- package/src/index.ts +1 -0
- package/src/lazy.js +1 -0
- package/src/registry.js +10 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { test, expect } from '@playwright/experimental-ct-react';
|
|
3
|
+
import TestVariant from '@digigov/ui/utils/TestVariant'
|
|
4
|
+
import { Default } from '@digigov/react-modules/Faq/__stories__/Default';
|
|
5
|
+
|
|
6
|
+
test('renders the All Faq variants', async ({ mount, page }) => {
|
|
7
|
+
await mount(
|
|
8
|
+
|
|
9
|
+
<div>
|
|
10
|
+
<TestVariant title="Default">
|
|
11
|
+
<Default />
|
|
12
|
+
</TestVariant>
|
|
13
|
+
</div>
|
|
14
|
+
)
|
|
15
|
+
await page.evaluate(() => document.fonts.ready);
|
|
16
|
+
|
|
17
|
+
// Move the mouse to the top-left corner to avoid random hover issues
|
|
18
|
+
await page.mouse.move(0, 0);
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
const screenshot = await page.screenshot({ fullPage: true, animations: 'disabled' });
|
|
22
|
+
expect(screenshot).toMatchSnapshot();
|
|
23
|
+
});
|
|
24
|
+
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import React, { useEffect, useContext } from 'react';
|
|
2
|
+
import { Field } from '@digigov/form/Field';
|
|
3
|
+
import FormBuilder from '@digigov/form/FormBuilder';
|
|
4
|
+
import { FormContext } from '@digigov/form/FormContext';
|
|
5
|
+
import Results from '@digigov/react-modules/Faq/Results';
|
|
6
|
+
import { createId } from '@digigov/react-modules/Faq/utils';
|
|
7
|
+
import PageTitleContainer, {
|
|
8
|
+
PageTitleHeading,
|
|
9
|
+
} from '@digigov/ui/app/PageTitleContainer';
|
|
10
|
+
import {
|
|
11
|
+
Accordion,
|
|
12
|
+
AccordionSection,
|
|
13
|
+
AccordionSectionContent,
|
|
14
|
+
AccordionSectionSummary,
|
|
15
|
+
AccordionSectionSummaryHeading,
|
|
16
|
+
} from '@digigov/ui/content/Accordion';
|
|
17
|
+
import { useAccordion } from '@digigov/ui/content/Accordion/hooks';
|
|
18
|
+
import Markdown from '@digigov/ui/content/Markdown';
|
|
19
|
+
import { SearchButton } from '@digigov/ui/form/SearchContainer';
|
|
20
|
+
import { Stack } from '@digigov/ui/layouts';
|
|
21
|
+
import { Aside } from '@digigov/ui/layouts/Basic/Aside';
|
|
22
|
+
import { Container } from '@digigov/ui/layouts/Basic/Container';
|
|
23
|
+
import { Main } from '@digigov/ui/layouts/Basic/Main';
|
|
24
|
+
import Grid from '@digigov/ui/layouts/Grid';
|
|
25
|
+
import SectionBreak from '@digigov/ui/layouts/SectionBreak';
|
|
26
|
+
import { BackToTop } from '@digigov/ui/navigation/BackToTopLink';
|
|
27
|
+
import NavList, { NavListItemAction } from '@digigov/ui/navigation/NavList';
|
|
28
|
+
import { Heading } from '@digigov/ui/typography/Heading';
|
|
29
|
+
import Hint from '@digigov/ui/typography/Hint';
|
|
30
|
+
|
|
31
|
+
export interface sectionsConfigType {
|
|
32
|
+
sections: SectionType[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface QaType {
|
|
36
|
+
id?: string;
|
|
37
|
+
question: string;
|
|
38
|
+
answer: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SectionType {
|
|
42
|
+
id: string;
|
|
43
|
+
title: string;
|
|
44
|
+
qa: QaType[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface TocType {
|
|
48
|
+
title: string;
|
|
49
|
+
placement: 'top' | 'left' | 'right' | 'none';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface SearchFilterType {
|
|
53
|
+
title?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ContentsType {
|
|
57
|
+
title: string;
|
|
58
|
+
toc: TocType;
|
|
59
|
+
search?: SearchFilterType;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface NavigationListProps {
|
|
63
|
+
title?: string;
|
|
64
|
+
sections: SectionType[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface FaqProps {
|
|
68
|
+
contents: ContentsType;
|
|
69
|
+
sections: SectionType[];
|
|
70
|
+
initialSections: sectionsConfigType;
|
|
71
|
+
search: (values: Record<string, string>) => void;
|
|
72
|
+
submitValues: { text: string };
|
|
73
|
+
activeQa: string;
|
|
74
|
+
onActiveQa: (v: string) => void;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const FormBuilderSyncValues = ({ values, autoSubmit }) => {
|
|
78
|
+
const form = useContext(FormContext);
|
|
79
|
+
const previousValues = form.getValues();
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
const mergedObject = { ...values, ...previousValues };
|
|
82
|
+
let shouldSubmit = false;
|
|
83
|
+
for (const key in mergedObject) {
|
|
84
|
+
// catching the filters that have been parsed from url & avoid continuous submitting
|
|
85
|
+
if (values[key] !== undefined && previousValues[key] !== values[key]) {
|
|
86
|
+
shouldSubmit = true;
|
|
87
|
+
previousValues[key] = values[key];
|
|
88
|
+
form.setValue(key, values[key]);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (autoSubmit && shouldSubmit) {
|
|
92
|
+
form.submit();
|
|
93
|
+
}
|
|
94
|
+
}, [autoSubmit, form, previousValues, values]);
|
|
95
|
+
return <></>;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const NavigationList = React.forwardRef<HTMLUListElement, NavigationListProps>(
|
|
99
|
+
function NavigationList({ title, sections }, ref) {
|
|
100
|
+
return (
|
|
101
|
+
<NavList ref={ref} layout="vertical" marginBottom={10}>
|
|
102
|
+
{title && (
|
|
103
|
+
<Heading size="md" id="contents" marginBottom={4}>
|
|
104
|
+
{title}
|
|
105
|
+
</Heading>
|
|
106
|
+
)}
|
|
107
|
+
{sections &&
|
|
108
|
+
sections.length > 0 &&
|
|
109
|
+
sections.map(({ id, title }, index) => (
|
|
110
|
+
<NavListItemAction key={index} href={`#${createId(id, title)}`}>
|
|
111
|
+
{title}
|
|
112
|
+
</NavListItemAction>
|
|
113
|
+
))}
|
|
114
|
+
</NavList>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
export const Faq = React.forwardRef<HTMLDivElement, FaqProps>(function FAQ(
|
|
120
|
+
{
|
|
121
|
+
contents,
|
|
122
|
+
sections,
|
|
123
|
+
initialSections,
|
|
124
|
+
submitValues,
|
|
125
|
+
activeQa,
|
|
126
|
+
onActiveQa,
|
|
127
|
+
search,
|
|
128
|
+
},
|
|
129
|
+
ref
|
|
130
|
+
) {
|
|
131
|
+
const { section, currentOpen, onOpen, close } = useAccordion({
|
|
132
|
+
singleOpen: true,
|
|
133
|
+
defaultOpen: 0,
|
|
134
|
+
});
|
|
135
|
+
const placement = contents.toc?.placement || 'none';
|
|
136
|
+
const filteredSections = sections.reduce(
|
|
137
|
+
(acc, section) => acc + (section.qa.length || 0),
|
|
138
|
+
0
|
|
139
|
+
);
|
|
140
|
+
const primarySections = initialSections.sections.reduce(
|
|
141
|
+
(acc, section) => acc + (section.qa.length || 0),
|
|
142
|
+
0
|
|
143
|
+
);
|
|
144
|
+
const hash = window.location.hash.slice(1);
|
|
145
|
+
const currentId = activeQa ? activeQa : hash;
|
|
146
|
+
|
|
147
|
+
useEffect(() => {
|
|
148
|
+
if (onActiveQa) {
|
|
149
|
+
if (currentOpen && activeQa !== currentOpen) {
|
|
150
|
+
onActiveQa(currentOpen as string);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}, [activeQa, currentOpen, onActiveQa]);
|
|
154
|
+
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
if (activeQa && activeQa !== currentOpen) {
|
|
157
|
+
onOpen(activeQa);
|
|
158
|
+
}
|
|
159
|
+
}, [activeQa, currentOpen, onOpen]);
|
|
160
|
+
|
|
161
|
+
useEffect(() => {
|
|
162
|
+
// Scroll to the target element if it exists
|
|
163
|
+
if (currentId) {
|
|
164
|
+
const element = document.getElementById(currentId);
|
|
165
|
+
if (element) {
|
|
166
|
+
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}, [activeQa, currentId, hash]);
|
|
170
|
+
|
|
171
|
+
const Onclose = (activeQa) => {
|
|
172
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
173
|
+
urlParams.delete('text');
|
|
174
|
+
urlParams.delete('activeQa');
|
|
175
|
+
window.history.pushState({}, '', '?' + urlParams.toString());
|
|
176
|
+
onActiveQa('');
|
|
177
|
+
close(activeQa);
|
|
178
|
+
};
|
|
179
|
+
const handleSubmit = (data) => {
|
|
180
|
+
search(data);
|
|
181
|
+
onActiveQa('');
|
|
182
|
+
close(activeQa);
|
|
183
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
184
|
+
urlParams.delete('activeQa');
|
|
185
|
+
window.history.replaceState({}, '', '?' + urlParams.toString());
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<Container ref={ref}>
|
|
190
|
+
{placement !== 'none' && placement === 'left' && (
|
|
191
|
+
<Aside sticky={false}>
|
|
192
|
+
<NavigationList title={contents.toc?.title} sections={sections} />
|
|
193
|
+
</Aside>
|
|
194
|
+
)}
|
|
195
|
+
<Main>
|
|
196
|
+
<PageTitleContainer>
|
|
197
|
+
<PageTitleHeading size="xl" id="faq">
|
|
198
|
+
{contents?.title}
|
|
199
|
+
</PageTitleHeading>
|
|
200
|
+
</PageTitleContainer>
|
|
201
|
+
{placement !== 'none' && placement === 'top' && (
|
|
202
|
+
<NavigationList title={contents?.toc?.title} sections={sections} />
|
|
203
|
+
)}
|
|
204
|
+
|
|
205
|
+
{contents.search && (
|
|
206
|
+
<FormBuilder onSubmit={handleSubmit} initial={{ text: '' }}>
|
|
207
|
+
{submitValues && (
|
|
208
|
+
<FormBuilderSyncValues values={submitValues} autoSubmit={true} />
|
|
209
|
+
)}
|
|
210
|
+
<Stack
|
|
211
|
+
direction="row"
|
|
212
|
+
flexWrap="nowrap"
|
|
213
|
+
alignItems="flex-end"
|
|
214
|
+
spacing={4}
|
|
215
|
+
>
|
|
216
|
+
<Grid container style={{ width: '100%' }}>
|
|
217
|
+
<Field
|
|
218
|
+
type="string"
|
|
219
|
+
key="text"
|
|
220
|
+
name="text"
|
|
221
|
+
placeholder="Αναζητήστε σχετικά με την ερώτησή σας"
|
|
222
|
+
label={{ primary: contents.search.title }}
|
|
223
|
+
/>
|
|
224
|
+
</Grid>
|
|
225
|
+
<SearchButton
|
|
226
|
+
type="submit"
|
|
227
|
+
mb={{ md: 10 }}
|
|
228
|
+
style={{ minHeight: '2.75rem' }}
|
|
229
|
+
/>
|
|
230
|
+
</Stack>
|
|
231
|
+
{filteredSections !== primarySections && (
|
|
232
|
+
<Results
|
|
233
|
+
filteredSections={filteredSections}
|
|
234
|
+
primarySections={primarySections}
|
|
235
|
+
Onclose={Onclose}
|
|
236
|
+
activeQa={activeQa}
|
|
237
|
+
/>
|
|
238
|
+
)}
|
|
239
|
+
</FormBuilder>
|
|
240
|
+
)}
|
|
241
|
+
<Grid>
|
|
242
|
+
{sections && sections.length > 0 ? (
|
|
243
|
+
sections.map(({ id: sectionId, title, qa }, index) => (
|
|
244
|
+
<React.Fragment key={index}>
|
|
245
|
+
<Heading id={createId(sectionId, title)} size="lg">
|
|
246
|
+
{title}
|
|
247
|
+
</Heading>
|
|
248
|
+
<Accordion marginBottom={qa && qa.length > 0 ? 12 : 0}>
|
|
249
|
+
{qa?.map(({ id, question, answer }, indx) => (
|
|
250
|
+
<AccordionSection
|
|
251
|
+
key={indx}
|
|
252
|
+
{...section(createId(id, question))}
|
|
253
|
+
>
|
|
254
|
+
<AccordionSectionSummary>
|
|
255
|
+
<AccordionSectionSummaryHeading
|
|
256
|
+
aria-controls={createId(id, question)}
|
|
257
|
+
>
|
|
258
|
+
{question}
|
|
259
|
+
</AccordionSectionSummaryHeading>
|
|
260
|
+
</AccordionSectionSummary>
|
|
261
|
+
<AccordionSectionContent id={createId(id, question)}>
|
|
262
|
+
<Markdown content={answer} />
|
|
263
|
+
</AccordionSectionContent>
|
|
264
|
+
</AccordionSection>
|
|
265
|
+
))}
|
|
266
|
+
</Accordion>
|
|
267
|
+
<SectionBreak visible={false} />
|
|
268
|
+
</React.Fragment>
|
|
269
|
+
))
|
|
270
|
+
) : (
|
|
271
|
+
<Hint marginBottom={10}>Δεν βρέθηκαν αποτελέσματα.</Hint>
|
|
272
|
+
)}
|
|
273
|
+
</Grid>
|
|
274
|
+
<BackToTop topLimitId="contents" id="back-to-top">
|
|
275
|
+
Επιστροφή στα Περιεχόμενα
|
|
276
|
+
</BackToTop>
|
|
277
|
+
</Main>
|
|
278
|
+
{placement !== 'none' && placement === 'right' && (
|
|
279
|
+
<Aside sticky={false}>
|
|
280
|
+
<NavigationList title={contents?.toc?.title} sections={sections} />
|
|
281
|
+
</Aside>
|
|
282
|
+
)}
|
|
283
|
+
</Container>
|
|
284
|
+
);
|
|
285
|
+
});
|
|
286
|
+
export default Faq;
|
package/src/Faq/slug.ts
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export function slug(text: string, maxWidth = 50): string {
|
|
2
|
+
// Greek to Latin character mapping
|
|
3
|
+
const greekToLatinMap: Record<string, string> = {
|
|
4
|
+
α: 'a',
|
|
5
|
+
β: 'b',
|
|
6
|
+
γ: 'g',
|
|
7
|
+
δ: 'd',
|
|
8
|
+
ε: 'e',
|
|
9
|
+
ζ: 'z',
|
|
10
|
+
η: 'i',
|
|
11
|
+
θ: 'th',
|
|
12
|
+
ι: 'i',
|
|
13
|
+
κ: 'k',
|
|
14
|
+
λ: 'l',
|
|
15
|
+
μ: 'm',
|
|
16
|
+
ν: 'n',
|
|
17
|
+
ξ: 'x',
|
|
18
|
+
ο: 'o',
|
|
19
|
+
π: 'p',
|
|
20
|
+
ρ: 'r',
|
|
21
|
+
σ: 's',
|
|
22
|
+
τ: 't',
|
|
23
|
+
υ: 'y',
|
|
24
|
+
φ: 'f',
|
|
25
|
+
χ: 'ch',
|
|
26
|
+
ψ: 'ps',
|
|
27
|
+
ω: 'o',
|
|
28
|
+
ά: 'a',
|
|
29
|
+
έ: 'e',
|
|
30
|
+
ί: 'i',
|
|
31
|
+
ό: 'o',
|
|
32
|
+
ύ: 'y',
|
|
33
|
+
ή: 'i',
|
|
34
|
+
ώ: 'o',
|
|
35
|
+
ς: 's',
|
|
36
|
+
ϊ: 'i',
|
|
37
|
+
ΰ: 'y',
|
|
38
|
+
ϋ: 'y',
|
|
39
|
+
ΐ: 'i',
|
|
40
|
+
Α: 'A',
|
|
41
|
+
Β: 'B',
|
|
42
|
+
Γ: 'G',
|
|
43
|
+
Δ: 'D',
|
|
44
|
+
Ε: 'E',
|
|
45
|
+
Ζ: 'Z',
|
|
46
|
+
Η: 'I',
|
|
47
|
+
Θ: 'TH',
|
|
48
|
+
Ι: 'I',
|
|
49
|
+
Κ: 'K',
|
|
50
|
+
Λ: 'L',
|
|
51
|
+
Μ: 'M',
|
|
52
|
+
Ν: 'N',
|
|
53
|
+
Ξ: 'X',
|
|
54
|
+
Ο: 'O',
|
|
55
|
+
Π: 'P',
|
|
56
|
+
Ρ: 'R',
|
|
57
|
+
Σ: 'S',
|
|
58
|
+
Τ: 'T',
|
|
59
|
+
Υ: 'Y',
|
|
60
|
+
Φ: 'F',
|
|
61
|
+
Χ: 'CH',
|
|
62
|
+
Ψ: 'PS',
|
|
63
|
+
Ω: 'O',
|
|
64
|
+
Ά: 'A',
|
|
65
|
+
Έ: 'E',
|
|
66
|
+
Ί: 'I',
|
|
67
|
+
Ό: 'O',
|
|
68
|
+
Ύ: 'Y',
|
|
69
|
+
Ή: 'I',
|
|
70
|
+
Ώ: 'O',
|
|
71
|
+
Ϊ: 'I',
|
|
72
|
+
Ϋ: 'Y',
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Convert Greek characters to Latin
|
|
76
|
+
const latinText = text
|
|
77
|
+
.split('')
|
|
78
|
+
.map((char) => greekToLatinMap[char] || char)
|
|
79
|
+
.join('');
|
|
80
|
+
|
|
81
|
+
// Convert to lowercase, replace spaces with hyphens, remove special characters
|
|
82
|
+
const processedText = latinText
|
|
83
|
+
.toLowerCase()
|
|
84
|
+
.replace(/\s+/g, '-')
|
|
85
|
+
.replace(/[^\w-]+/g, '')
|
|
86
|
+
.replace(/--+/g, '-')
|
|
87
|
+
.replace(/^-+/, '')
|
|
88
|
+
.replace(/-+$/, '');
|
|
89
|
+
|
|
90
|
+
// Calculate the available width for the slug (subtracting 1 for the hyphen and at least 8 for the ID)
|
|
91
|
+
// const availableWidth = Math.max(0, maxWidth - 9);
|
|
92
|
+
|
|
93
|
+
// Split the processed text into slug and remaining text for ID
|
|
94
|
+
let slug = processedText.substring(0, maxWidth);
|
|
95
|
+
const remainingText = processedText.substring(maxWidth);
|
|
96
|
+
|
|
97
|
+
// Remove trailing hyphens from the slug
|
|
98
|
+
slug = slug.replace(/-+$/, '');
|
|
99
|
+
|
|
100
|
+
// Generate ID from the remaining text
|
|
101
|
+
const id = generateIDFromText(remainingText);
|
|
102
|
+
|
|
103
|
+
// Combine the slug and ID
|
|
104
|
+
return `${slug}${id && '-'}${id}`;
|
|
105
|
+
}
|
|
106
|
+
function generateIDFromText(text: string): string {
|
|
107
|
+
// If text is empty or maxLength is 0 or less, return a default ID
|
|
108
|
+
if (!text) return '';
|
|
109
|
+
|
|
110
|
+
// Remove hyphens and take only alphanumeric characters
|
|
111
|
+
let processedText = text.replace(/-/g, '').replace(/[^a-z0-9]/g, '');
|
|
112
|
+
|
|
113
|
+
// If processed text is empty, use a default base
|
|
114
|
+
if (!processedText) processedText = 'default';
|
|
115
|
+
|
|
116
|
+
// Calculate a simple hash of the processed text
|
|
117
|
+
let hash = 0;
|
|
118
|
+
for (let i = 0; i < processedText.length; i++) {
|
|
119
|
+
const char = processedText.charCodeAt(i);
|
|
120
|
+
hash = (hash << 5) - hash + char;
|
|
121
|
+
hash = hash & hash; // Convert to 32-bit integer
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Convert hash to a positive number and then to base 36 (0-9 and a-z)
|
|
125
|
+
const id = Math.abs(hash).toString(36);
|
|
126
|
+
|
|
127
|
+
// Ensure the ID is at least 8 characters long, padding with '0' if necessary
|
|
128
|
+
return id;
|
|
129
|
+
// return id.padEnd(8, '0').substring(0, maxLength);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Test the function
|
|
133
|
+
// console.log(createSlugWithID('Καλημέρα κόσμε! Hello world!', 10));
|
|
134
|
+
// console.log(createSlugWithID('Ελληνικά και English mixed', 80));
|
|
135
|
+
// console.log(
|
|
136
|
+
// createSlugWithID(
|
|
137
|
+
// 'Αυτό είναι ένα πολύ μεγάλο κείμενο για να δοκιμάσουμε το όριο πλάτους',
|
|
138
|
+
// 90
|
|
139
|
+
// )
|
|
140
|
+
// );
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { test, expect } from '@playwright/experimental-ct-react';
|
|
3
|
+
|
|
4
|
+
import { Default } from '@digigov/react-modules/Faq/__stories__/Default';
|
|
5
|
+
|
|
6
|
+
test('renders the Default', async ({ mount, page }) => {
|
|
7
|
+
await mount(
|
|
8
|
+
<Default />
|
|
9
|
+
)
|
|
10
|
+
await page.evaluate(() => document.fonts.ready);
|
|
11
|
+
|
|
12
|
+
// Move the mouse to the top-left corner to avoid random hover issues
|
|
13
|
+
await page.mouse.move(0, 0);
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
const screenshot = await page.screenshot({ fullPage: true, animations: 'disabled' });
|
|
17
|
+
expect(screenshot).toMatchSnapshot();
|
|
18
|
+
});
|
|
19
|
+
|
package/src/Faq/utils.ts
ADDED
|
@@ -14,6 +14,10 @@ test('renders the All FilteredResults variants', async ({ mount, page }) => {
|
|
|
14
14
|
)
|
|
15
15
|
await page.evaluate(() => document.fonts.ready);
|
|
16
16
|
|
|
17
|
+
// Move the mouse to the top-left corner to avoid random hover issues
|
|
18
|
+
await page.mouse.move(0, 0);
|
|
19
|
+
|
|
20
|
+
|
|
17
21
|
const screenshot = await page.screenshot({ fullPage: true, animations: 'disabled' });
|
|
18
22
|
expect(screenshot).toMatchSnapshot();
|
|
19
23
|
});
|
|
@@ -9,6 +9,10 @@ test('renders the Default', async ({ mount, page }) => {
|
|
|
9
9
|
)
|
|
10
10
|
await page.evaluate(() => document.fonts.ready);
|
|
11
11
|
|
|
12
|
+
// Move the mouse to the top-left corner to avoid random hover issues
|
|
13
|
+
await page.mouse.move(0, 0);
|
|
14
|
+
|
|
15
|
+
|
|
12
16
|
const screenshot = await page.screenshot({ fullPage: true, animations: 'disabled' });
|
|
13
17
|
expect(screenshot).toMatchSnapshot();
|
|
14
18
|
});
|
package/src/index.ts
CHANGED
package/src/lazy.js
CHANGED
|
@@ -4,6 +4,7 @@ export default {
|
|
|
4
4
|
'DrawerFilteredResults': lazy(() => import('@digigov/react-modules/FilteredResults').then((module) => ({ default: module['DrawerFilteredResults'] }))),
|
|
5
5
|
'BlockFilteredResults': lazy(() => import('@digigov/react-modules/FilteredResults').then((module) => ({ default: module['BlockFilteredResults'] }))),
|
|
6
6
|
'FilteredResults': lazy(() => import('@digigov/react-modules/FilteredResults').then((module) => ({ default: module['FilteredResults'] }))),
|
|
7
|
+
'Faq': lazy(() => import('@digigov/react-modules/Faq').then((module) => ({ default: module['Faq'] }))),
|
|
7
8
|
'DataTable': lazy(() => import('@digigov/react-modules/FilteredResults/DataTable').then((module) => ({ default: module['DataTable'] }))),
|
|
8
9
|
'FilterChips': lazy(() => import('@digigov/react-modules/FilteredResults/FilterChips').then((module) => ({ default: module['FilterChips'] }))),
|
|
9
10
|
'FilterFields': lazy(() => import('@digigov/react-modules/FilteredResults/FilterFields').then((module) => ({ default: module['FilterFields'] })))
|
package/src/registry.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
import * as _digigov_react_modules from "@digigov/react-modules";
|
|
3
|
+
import * as _digigov_react_modules_Faq_Results from "@digigov/react-modules/Faq/Results";
|
|
4
|
+
import * as _digigov_react_modules_Faq_hooks from "@digigov/react-modules/Faq/hooks";
|
|
5
|
+
import * as _digigov_react_modules_Faq from "@digigov/react-modules/Faq";
|
|
6
|
+
import * as _digigov_react_modules_Faq_slug from "@digigov/react-modules/Faq/slug";
|
|
7
|
+
import * as _digigov_react_modules_Faq_utils from "@digigov/react-modules/Faq/utils";
|
|
3
8
|
import * as _digigov_react_modules_FilteredResults_DataTable from "@digigov/react-modules/FilteredResults/DataTable";
|
|
4
9
|
import * as _digigov_react_modules_FilteredResults_FilterChips from "@digigov/react-modules/FilteredResults/FilterChips";
|
|
5
10
|
import * as _digigov_react_modules_FilteredResults_FilterFields from "@digigov/react-modules/FilteredResults/FilterFields";
|
|
@@ -25,6 +30,11 @@ function lazyImport(pkgImport) {
|
|
|
25
30
|
}
|
|
26
31
|
export default {
|
|
27
32
|
'@digigov/react-modules': lazyImport(_digigov_react_modules),
|
|
33
|
+
'@digigov/react-modules/Faq/Results': lazyImport(_digigov_react_modules_Faq_Results),
|
|
34
|
+
'@digigov/react-modules/Faq/hooks': lazyImport(_digigov_react_modules_Faq_hooks),
|
|
35
|
+
'@digigov/react-modules/Faq': lazyImport(_digigov_react_modules_Faq),
|
|
36
|
+
'@digigov/react-modules/Faq/slug': lazyImport(_digigov_react_modules_Faq_slug),
|
|
37
|
+
'@digigov/react-modules/Faq/utils': lazyImport(_digigov_react_modules_Faq_utils),
|
|
28
38
|
'@digigov/react-modules/FilteredResults/DataTable': lazyImport(_digigov_react_modules_FilteredResults_DataTable),
|
|
29
39
|
'@digigov/react-modules/FilteredResults/FilterChips': lazyImport(_digigov_react_modules_FilteredResults_FilterChips),
|
|
30
40
|
'@digigov/react-modules/FilteredResults/FilterFields': lazyImport(_digigov_react_modules_FilteredResults_FilterFields),
|