Skip to content

Commit fde2640

Browse files
committed
Merge branch 'main' into vnext
2 parents cb9f2a7 + afcdb7e commit fde2640

File tree

56 files changed

+1209
-855
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1209
-855
lines changed

index.html

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,19 @@
9494
padding-top: 0;
9595
padding-bottom: 4rem;
9696
}
97-
.info__company {
97+
h1 {
9898
display: flex;
99-
align-items: center;
100-
gap: 3%;
99+
flex-direction: column;
101100
}
102101
.info__company img {
103102
width: 12%;
104103
height: 100%;
105104
margin-top: 4px;
106105
}
107-
.info__company h2 {
106+
.info__company {
107+
display: flex;
108+
align-items: center;
109+
gap: 3%;
108110
font-size: clamp(55px, 9vw, 10rem);
109111
color: var(--accent);
110112
background-image: linear-gradient(69deg, #96d9ab 30%, #ffffff 75%);
@@ -127,11 +129,11 @@
127129
padding-top: 0.9rem;
128130
width: 50%;
129131
}
130-
.info__text h3 {
132+
.info__first {
131133
font-weight: 400;
132134
font-size: 30px;
133135
}
134-
.info__text p {
136+
.info__community {
135137
font-size: 24px;
136138
padding-top: 1.2rem;
137139
color: #fc5969;
@@ -149,6 +151,7 @@
149151
font-weight: 600;
150152
letter-spacing: 0.2px;
151153
font-size: 20px;
154+
cursor: pointer;
152155
}
153156
.info__group {
154157
display: flex;
@@ -198,10 +201,10 @@
198201
.info__text {
199202
padding-top: 0;
200203
}
201-
.info__text h3 {
204+
.info__first {
202205
font-size: 26px;
203206
}
204-
.info__text p {
207+
.info__community {
205208
font-size: 20px;
206209
}
207210
.info__group {
@@ -284,10 +287,10 @@
284287
font-size: 18px;
285288
}
286289

287-
.info__text h3 {
290+
.info__first {
288291
font-size: 22px;
289292
}
290-
.info__text p {
293+
.info__community {
291294
font-size: 19px;
292295
}
293296
.github p {
@@ -304,7 +307,7 @@
304307
width: 70px;
305308
margin-top: 0;
306309
}
307-
.info__company h2 {
310+
.info__company {
308311
line-height: 1.1;
309312
}
310313
}
@@ -339,25 +342,28 @@
339342
</a>
340343
</header>
341344
<main class="main">
342-
<div class="info container">
343-
<div class="info__company">
344-
<img
345-
src="/assets/logo_mongo_modeler_dark_mode.svg"
346-
alt="Mongo Modeler Logo"
347-
/>
348-
<h2 class="info__company">Mongo Modeler</h2>
349-
</div>
350-
<h1 class="info__claim">
351-
A free, online Data Modeling tool for MongoDB.
345+
<section class="info container">
346+
<h1>
347+
<span class="info__company">
348+
<img
349+
src="/assets/logo_mongo_modeler_dark_mode.svg"
350+
alt="Mongo Modeler Logo"
351+
/>
352+
Mongo Modeler</span
353+
>
354+
<span class="info__claim">
355+
A free, online Data Modeling tool for MongoDB.
356+
</span>
352357
</h1>
353358
<div class="info__detail">
354359
<div class="info__text">
355-
<h3>
360+
<p class="info__first">
356361
Mongo Modeler is a <span class="highlight">free</span>, open
357362
source <span class="highlight">tool</span> for visualization of
358363
<span class="highlight">MongoDB</span> schema design
359-
</h3>
360-
<p>Community preview</p>
364+
</p>
365+
366+
<p class="info__community">Community preview</p>
361367
<div class="info__group">
362368
<a href="./editor.html" class="info__link"
363369
>Launch MongoDB Designer</a
@@ -374,17 +380,17 @@ <h3>
374380
></iframe>
375381
</div>
376382
</div>
377-
</div>
378-
<div class="github">
379-
<p class="container">
380-
Interested in suggesting a new feature or reporting a bug? Visit our
381-
project's Github page to make your contribution.
382-
<a href="https://github.com/Lemoncode/mongo-modeler" target="_blank"
383-
>Go to Github</a
384-
>
385-
</p>
386-
</div>
383+
</section>
387384
</main>
385+
<footer class="github">
386+
<p class="container">
387+
Interested in suggesting a new feature or reporting a bug? Visit our
388+
project's Github page to make your contribution.
389+
<a href="https://github.com/Lemoncode/mongo-modeler" target="_blank"
390+
>Go to Github</a
391+
>
392+
</p>
393+
</footer>
388394
<script>
389395
let installPrompt = null;
390396
const installButton = document.querySelector('#install');

src/common/a11y/click-outside.hook.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
3+
export const useClickOutside = (
4+
isOpen: boolean,
5+
ref: React.RefObject<HTMLElement>,
6+
callback: (e: MouseEvent) => void
7+
) => {
8+
const handleClickOutside = (e: MouseEvent) => {
9+
callback(e);
10+
};
11+
12+
React.useEffect(() => {
13+
ref.current?.addEventListener('click', handleClickOutside);
14+
15+
return () => {
16+
ref.current?.removeEventListener('click', handleClickOutside);
17+
};
18+
}, [isOpen]);
19+
};

src/common/a11y/common.model.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export type BaseA11yOption<Option> = Option & {
2+
tabIndex: number;
3+
};
4+
5+
export type NestedOption<Option> = {
6+
id: string;
7+
children?: Option[];
8+
};
9+
10+
export type FlatOption<Option extends NestedOption<Option>> = Omit<
11+
Option,
12+
'children'
13+
> & {
14+
parentId?: string;
15+
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const getArrowUpIndex = (currentIndex: number) => {
2+
const isFirstOption = currentIndex === 0;
3+
return isFirstOption ? currentIndex : currentIndex - 1;
4+
};
5+
6+
export const getArrowDownIndex = (currentIndex: number, options: any[]) => {
7+
const isLastOption = currentIndex === options.length - 1;
8+
return isLastOption ? currentIndex : currentIndex + 1;
9+
};
10+
11+
export const getFocusedOption = <FocusableOption extends { tabIndex: number }>(
12+
options: FocusableOption[]
13+
) => options.find(option => option.tabIndex === 0);

src/common/a11y/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export * from './select';
2+
export * from './nested-select';
3+
export * from './on-key.hook';
4+
export * from './focus.common-helpers';
5+
export * from './nested-list';
6+
export * from './common.model';

src/common/a11y/list/focus.helpers.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { BaseA11yOption } from '../common.model';
2+
3+
export const setInitialFocus = <
4+
Option,
5+
A11yOption extends BaseA11yOption<Option>,
6+
>(
7+
options: Option[]
8+
): A11yOption[] => {
9+
const a11ySelectionOptions = options.map<A11yOption>(
10+
(option, index) =>
11+
({
12+
...option,
13+
tabIndex: index === 0 ? 0 : -1,
14+
}) as unknown as A11yOption
15+
);
16+
17+
return a11ySelectionOptions;
18+
};
19+
20+
export const onFocusOption =
21+
<Option>(option: BaseA11yOption<Option>) =>
22+
(element: any) => {
23+
if (option.tabIndex === 0) {
24+
element?.focus();
25+
}
26+
};

src/common/a11y/list/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './list.hooks';
2+
export * from './list.model';

src/common/a11y/list/list.hooks.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import React from 'react';
2+
import { BaseA11yOption } from '../common.model';
3+
import { getArrowDownIndex, getArrowUpIndex } from '../focus.common-helpers';
4+
import { useOnKey } from '../on-key.hook';
5+
import { onFocusOption, setInitialFocus } from './focus.helpers';
6+
import { SetInitialFocusFn } from './list.model';
7+
import { useOnTwoKeys } from '../on-two-Keys.hook';
8+
9+
export const useA11yList = <Option, A11yOption extends BaseA11yOption<Option>>(
10+
options: Option[],
11+
onSetInitialFocus: SetInitialFocusFn<Option, A11yOption> = setInitialFocus
12+
) => {
13+
const optionListRef = React.useRef<any>(null);
14+
const [internalOptions, setInternalOptions] = React.useState<A11yOption[]>(
15+
onSetInitialFocus(options)
16+
);
17+
18+
const handleFocus = (event: KeyboardEvent) => {
19+
const currentIndex = internalOptions.findIndex(
20+
option => option.tabIndex === 0
21+
);
22+
const nextIndex =
23+
event.key === 'ArrowUp'
24+
? getArrowUpIndex(currentIndex)
25+
: getArrowDownIndex(currentIndex, internalOptions);
26+
27+
if (currentIndex !== nextIndex) {
28+
setInternalOptions(prevOptions =>
29+
prevOptions.map((option, index) => {
30+
switch (index) {
31+
case currentIndex:
32+
return {
33+
...option,
34+
tabIndex: -1,
35+
};
36+
case nextIndex:
37+
return {
38+
...option,
39+
tabIndex: 0,
40+
};
41+
default:
42+
return option;
43+
}
44+
})
45+
);
46+
}
47+
};
48+
49+
const handleFirstAndLast = (value: number) => {
50+
setInternalOptions(prevOptions =>
51+
prevOptions.map((option, index) => {
52+
switch (index) {
53+
case value:
54+
return {
55+
...option,
56+
tabIndex: 0,
57+
};
58+
default:
59+
return {
60+
...option,
61+
tabIndex: -1,
62+
};
63+
}
64+
})
65+
);
66+
};
67+
68+
//Need this for Mac users
69+
useOnTwoKeys(
70+
optionListRef,
71+
['ArrowUp', 'ArrowDown'],
72+
'Meta',
73+
(event: KeyboardEvent) =>
74+
event.key === 'ArrowUp'
75+
? handleFirstAndLast(0)
76+
: handleFirstAndLast(internalOptions.length - 1)
77+
);
78+
79+
useOnKey(optionListRef, ['ArrowDown', 'ArrowUp'], (event: KeyboardEvent) => {
80+
handleFocus(event);
81+
});
82+
83+
useOnKey(optionListRef, ['Home', 'End'], (event: KeyboardEvent) =>
84+
event.key === 'Home'
85+
? handleFirstAndLast(0)
86+
: handleFirstAndLast(internalOptions.length - 1)
87+
);
88+
89+
return {
90+
optionListRef,
91+
options: internalOptions,
92+
setOptions: setInternalOptions,
93+
onFocusOption,
94+
};
95+
};

src/common/a11y/list/list.model.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type SetInitialFocusFn<Option, A11yOption> = (
2+
options: Option[]
3+
) => A11yOption[];

src/common/a11y/nested-list/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './nested-list.hooks';
2+
export * from './nested-list.model';
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {
2+
mapFlatOptionsToNestedListOptions,
3+
mapNestedListOptionsToFlatOptions,
4+
} from './nested-list.mappers';
5+
import { NestedOption } from '../common.model';
6+
import { useA11yNested } from '../nested.hooks';
7+
import { useA11yList } from '../list';
8+
9+
export const useA11yNestedList = <Option extends NestedOption<Option>>(
10+
options: Option[]
11+
) => {
12+
const flatOptions = mapNestedListOptionsToFlatOptions(options);
13+
14+
const {
15+
optionListRef,
16+
options: internalOptions,
17+
setOptions,
18+
onFocusOption,
19+
} = useA11yList(flatOptions);
20+
21+
useA11yNested(optionListRef, internalOptions, setOptions);
22+
23+
return {
24+
optionListRef,
25+
options: mapFlatOptionsToNestedListOptions(internalOptions),
26+
setOptions,
27+
onFocusOption,
28+
};
29+
};

0 commit comments

Comments
 (0)