5htp-core 0.5.9-6 → 0.5.9-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.
@@ -69,6 +69,7 @@ export default function App({ context }: {
69
69
  SegmentedControl: { defaultProps: { size: 'md' } },
70
70
  Menu: { defaultProps: { size: 'md' } },
71
71
  MenuItem: { defaultProps: { size: 'md' } },
72
+ Autocomplete: { defaultProps: { size: 'md' } },
72
73
  // Add any others you use...
73
74
  },
74
75
  }} withGlobalStyles withNormalizeCSS>
@@ -18,6 +18,7 @@
18
18
  font-size: 1em;
19
19
  padding: 0 1.5em;
20
20
  height: @sizeComponent;
21
+ min-height: @sizeComponent;
21
22
 
22
23
  // Shape
23
24
  border-radius: @radius;
@@ -49,10 +49,6 @@ form {
49
49
  label {
50
50
  font-weight: 500;
51
51
  color: var(--cTxtBase);
52
-
53
- + p.desc {
54
- margin: 0;
55
- }
56
52
  }
57
53
 
58
54
  .row.champs,
@@ -29,7 +29,11 @@
29
29
  --mantine-SegmentedControl-height: @sizeComponent;
30
30
  }
31
31
 
32
-
32
+ .mantine-TextInput-wrapper textarea {
33
+ --input-line-height: 1.5;
34
+ --input-padding-y: @spacing;
35
+ --input-padding-x: @spacing;
36
+ }
33
37
 
34
38
 
35
39
 
@@ -47,6 +47,7 @@
47
47
 
48
48
  line-height: 1.5;
49
49
  text-align: left;
50
+ white-space: nowrap; // Don't line break in badges
50
51
 
51
52
  padding: 0.4em 0.8em;
52
53
 
@@ -78,23 +78,25 @@
78
78
  html {
79
79
  font-size: @sTxtPage;
80
80
  line-height: 1.25em;
81
- font-weight: 400;
82
81
  }
83
82
 
84
83
  * {
85
84
  box-sizing: border-box;
86
85
  outline: none;
87
86
  font-size: 1em;
87
+ font-weight: 500;
88
88
  padding: 0;
89
89
  margin: 0;
90
- // Avoids flexbox childrens to overflw parent
91
- min-width: 0;
92
90
 
93
91
  &, &:hover, &:focus {
94
92
  -webkit-tap-highlight-color: transparent;
95
93
  }
96
94
  }
97
95
 
96
+ p {
97
+ font-weight: 400;
98
+ }
99
+
98
100
  body {
99
101
  // Pas propre. A eviter (ex: perturbation smooth scroll
100
102
  //overflow-x: hidden;
@@ -42,15 +42,6 @@ p, .p {
42
42
  margin: 0; // Overwrite browser defaults
43
43
  }
44
44
 
45
- .desc {
46
- font-size: 0.8rem;
47
- color: var(--cTxtDesc);
48
-
49
- i {
50
- height: 1.16rem;
51
- }
52
- }
53
-
54
45
  // Gestion des dépassements
55
46
  //.bouton, // Empêche le label d'être affiché en mode icone only
56
47
  .bouton > .label /* <Select /> */ {
@@ -177,6 +177,11 @@
177
177
  .row,
178
178
  .col {
179
179
 
180
+ > * {
181
+ // Avoids flexbox childrens to overflw parent
182
+ min-width: 0;
183
+ }
184
+
180
185
  &.sp-btw { justify-content: space-between; }
181
186
  &.sp-ar { justify-content: space-around; }
182
187
  &.wrap { flex-wrap: wrap; }
@@ -8,21 +8,21 @@ import {
8
8
  SelectProps,
9
9
  MultiSelect as MantineMultiSelect,
10
10
  ComboboxItem,
11
-
12
- Menu,
13
- Button
11
+ Menu
14
12
  } from '@mantine/core';
15
13
  import Input from '@client/components/Input';
16
14
 
17
15
  // Core
18
16
  import { useMantineInput, InputBaseProps } from '@client/components/utils';
17
+ import Button, { Props as ButtonProps } from '@client/components/Button';
18
+ import Popover, { Props as PopoverProps } from '@client/components/containers/Popover';
19
19
 
20
20
  /*----------------------------------
21
21
  - TYPES
22
22
  ----------------------------------*/
23
23
 
24
24
  export type Props = SelectProps & InputBaseProps<ComboboxItem> & {
25
-
25
+ popoverProps?: PopoverProps
26
26
  }
27
27
 
28
28
  export type Choice = ComboboxItem;
@@ -37,8 +37,11 @@ const ensureChoice = (
37
37
  if (typeof choice === 'object')
38
38
  return choice;
39
39
 
40
+ // Ensure current is an array of choices
41
+ const allChoices = [...choices, ...current];
42
+
40
43
  // Find the choice
41
- const found = [...choices, ...current].find( c => c.value === choice );
44
+ const found = allChoices.find( c => c.value === choice );
42
45
  if (found) return found;
43
46
 
44
47
  // Create a new choice
@@ -60,11 +63,14 @@ export default (initProps: Props) => {
60
63
  onChange, value: current,
61
64
  required
62
65
  }, {
63
- multiple, choices: initChoices, enableSearch,
66
+ multiple, choices: initChoices, enableSearch, popoverProps,
64
67
  ...props
65
68
  }] = useMantineInput<Props, string|number>(initProps);
66
69
 
67
- const currentArray = Array.isArray(current) ? current : current ? [current] : [];
70
+ const currentArray = (Array.isArray(current)
71
+ ? current
72
+ : current ? [current] : []
73
+ ).map(c => ensureChoice(c, [], []));
68
74
 
69
75
  const choicesViaFunc = typeof initChoices === 'function';
70
76
  if (choicesViaFunc)
@@ -146,33 +152,14 @@ export default (initProps: Props) => {
146
152
 
147
153
  if (minimal) {
148
154
  return (
149
- <Menu width={300} opened={opened} onChange={setOpened}
150
- trapFocus withArrow shadow='lg'
151
- closeOnItemClick={!multiple}>
152
- <Menu.Target>
153
- <Button variant="subtle"
154
- leftSection={(
155
- (current && multiple) ? (
156
- <span class="badge bg info s">
157
- {current.length}
158
- </span>
159
- ) : null
160
- )}
161
- rightSection={<i src="angle-down" />}
162
- onClick={() => setOpened((o) => !o)} >
163
-
164
- {props.label || props.placeholder}
165
-
166
- </Button>
167
- </Menu.Target>
168
- <Menu.Dropdown>
169
-
155
+ <Popover {...(popoverProps || {})} state={[opened, setOpened]} content={(
156
+ <div class="card col menu floating">
170
157
  {enableSearch && <>
158
+
171
159
  <Input title="Search" value={search.keywords}
172
160
  wrapper={false} minimal icon="search"
173
161
  onChange={v => setSearch(s => ({ ...s, keywords: v }))} />
174
162
 
175
- <Menu.Divider />
176
163
  </>}
177
164
 
178
165
  {choices.map(choice => {
@@ -182,8 +169,9 @@ export default (initProps: Props) => {
182
169
  : props.value === choice.value;
183
170
 
184
171
  return (
185
- <Menu.Item key={choice.value}
186
- rightSection={isSelected ? <i src="check" /> : null}
172
+ <Button key={choice.value}
173
+ size="s"
174
+ suffix={isSelected ? <i src="check" /> : null}
187
175
  onClick={() => onChange( multiple
188
176
  ? (isSelected
189
177
  ? current.filter(c => c.value !== choice.value)
@@ -195,11 +183,26 @@ export default (initProps: Props) => {
195
183
  )
196
184
  )}>
197
185
  {choice.label}
198
- </Menu.Item>
186
+ </Button>
199
187
  )
200
188
  })}
201
- </Menu.Dropdown>
202
- </Menu>
189
+ </div>
190
+ )}>
191
+ <Button
192
+ prefix={(
193
+ (multiple && current?.length) ? (
194
+ <span class="badge bg info s">
195
+ {current.length}
196
+ </span>
197
+ ) : icon ? <i src={icon} /> : null
198
+ )}
199
+ suffix={iconR ? <i src={iconR} /> : <i src="angle-down" />}
200
+ onClick={() => setOpened((o) => !o)}>
201
+
202
+ {props.label || props.placeholder}
203
+
204
+ </Button>
205
+ </Popover>
203
206
  )
204
207
 
205
208
  } else {
@@ -34,6 +34,7 @@ export type Props<TRow> = {
34
34
  // Interactions
35
35
  sort?: TSortOptions,
36
36
  onSort?: (columnId: string | null, order: TSortOptions["order"]) => void,
37
+ onCellClick?: (row: TRow) => void,
37
38
 
38
39
  selection?: [TRow[], React.SetStateAction<TRow[]>],
39
40
  maxSelection?: number,
@@ -58,6 +59,7 @@ type TSortOptions = {
58
59
  export default function Liste<TRow extends TDonneeInconnue>({
59
60
  stickyHeader, onSort, sort: sorted,
60
61
  data: rows, setData, empty,
62
+ onCellClick,
61
63
  selection: selectionState, maxSelection,
62
64
  columns, ...props
63
65
  }: Props<TRow>) {
@@ -167,6 +169,11 @@ export default function Liste<TRow extends TDonneeInconnue>({
167
169
  );
168
170
  }
169
171
 
172
+ if (onCellClick) {
173
+ cellProps.onClick = () => onCellClick(row);
174
+ classe += ' clickable';
175
+ }
176
+
170
177
  let render: ComponentChild;
171
178
  if (Array.isArray(cell)) {
172
179
 
@@ -31,7 +31,7 @@ export {
31
31
  UnstyledButton,
32
32
  VisuallyHidden,
33
33
  Paper,
34
- //Popover,
34
+ Popover as PopoverMantine,
35
35
  ActionIcon,
36
36
  CloseButton,
37
37
  Group,
@@ -106,7 +106,7 @@ export {
106
106
  RangeSlider,
107
107
  RingProgress,
108
108
  SegmentedControl,
109
- //Select,
109
+ Select as SelectMantine,
110
110
  SemiCircleProgress,
111
111
  SimpleGrid,
112
112
  Skeleton,
@@ -127,7 +127,7 @@ type THookName = 'page.change' | 'page.changed' | 'page.rendered'
127
127
 
128
128
  type Config<TAdditionnalContext extends {} = {}> = {
129
129
  preload: string[], // List of globs
130
- context: (context: ClientContext, router: ClientRouter) => TAdditionnalContext,
130
+ context: (context: {}, router: ClientRouter) => TAdditionnalContext,
131
131
  }
132
132
 
133
133
  /*----------------------------------
@@ -2,6 +2,9 @@
2
2
  - DEPENDANCES
3
3
  ----------------------------------*/
4
4
 
5
+ // Npm
6
+ import zod from 'zod';
7
+
5
8
  // types
6
9
  import type {
7
10
  default as ClientRouter,
@@ -42,6 +45,7 @@ export type TRoute<RouterContext extends TClientOrServerContextForPage = TClient
42
45
  path: string,
43
46
 
44
47
  // Execute
48
+ schema?: zod.ZodSchema,
45
49
  controller: TRouteController<RouterContext>,
46
50
  options: TRouteOptions
47
51
  } & (
@@ -67,7 +71,8 @@ export type TErrorRoute<RouterContext extends TClientOrServerContextForPage = TC
67
71
  export type TAnyRoute<RouterContext extends TClientOrServerContextForPage = TClientOrServerContextForPage> =
68
72
  TRoute<RouterContext> | TErrorRoute<RouterContext>
69
73
 
70
- export type TClientOrServerContext = ClientRouterContext | ServerRouterContext;
74
+ // ClientRouterContext already includes server context
75
+ export type TClientOrServerContext = ClientRouterContext;// | ServerRouterContext;
71
76
 
72
77
  export type TClientOrServerContextForPage = With<TClientOrServerContext, 'page'>
73
78
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "5htp-core",
3
3
  "description": "Convenient TypeScript framework designed for Performance and Productivity.",
4
- "version": "0.5.9-6",
4
+ "version": "0.5.9-7",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/5htp-core.git",
7
7
  "license": "MIT",
@@ -16,7 +16,7 @@ import ServicesContainer, {
16
16
  import type { ServerBug } from './container/console';
17
17
 
18
18
  // Built-in
19
- import type { default as Router, Request as ServerRequest } from '@server/services/router';
19
+ import type { default as Router, Request as ServerRequest, TRoute } from '@server/services/router';
20
20
 
21
21
  export { default as Services } from './service/container';
22
22
  export type { TEnvConfig as Environment } from './container/config';
@@ -187,7 +187,7 @@ export abstract class Application<
187
187
  console.log('-' + '-'.repeat(level * 1), propKey + ': ' + service.constructor.name);
188
188
 
189
189
  // Routes
190
- const routes = service.__routes;
190
+ const routes = service.__routes as TRoute[];
191
191
  if (routes) for (const route of routes) {
192
192
 
193
193
  console.log('Attached service', service.constructor.name, 'to route', route.path);
@@ -196,9 +196,9 @@ export abstract class Application<
196
196
  route.controller = (context: RouterContext) => {
197
197
 
198
198
  // Filter data
199
- const data = route.options.validate
200
- ? route.options.validate( context.schema )
201
- : context.request.data;
199
+ const data = route.schema
200
+ ? route.schema.parse( context.request.data )
201
+ : {};
202
202
 
203
203
  // Run controller
204
204
  return origController.bind( service )(
@@ -8,6 +8,8 @@ import type { Command } from "../commands";
8
8
  import type { TServiceMetas } from './container';
9
9
  import type { TControllerDefinition, TRoute } from '../../services/router';
10
10
 
11
+ export { default as schema } from 'zod';
12
+
11
13
  /*----------------------------------
12
14
  - TYPES: OPTIONS
13
15
  ----------------------------------*/
@@ -71,6 +73,7 @@ export function Route(options: Omit<TControllerDefinition, 'controller'> = {}) {
71
73
  method: 'POST',
72
74
  path: '/api/' + options.path,
73
75
  controller: originalMethod,
76
+ schema: options.schema,
74
77
  options: {
75
78
  priority: options.priority || 0
76
79
  }
@@ -71,7 +71,7 @@ export default abstract class AuthService<
71
71
  TRequest extends ServerRequest<Router> = ServerRequest<Router>,
72
72
  > extends Service<TConfig, THooks, TApplication> {
73
73
 
74
- public abstract login( ...args: any[] ): Promise<{ user: TUser, token: string }>;
74
+ //public abstract login( ...args: any[] ): Promise<{ user: TUser, token: string }>;
75
75
  public abstract decodeSession( jwt: TJwtSession, req: THttpRequest ): Promise<TUser | null>;
76
76
 
77
77
  // https://beeceptor.com/docs/concepts/authorization-header/#examples
@@ -14,6 +14,7 @@
14
14
  import type express from 'express';
15
15
  import type { Request, Response, NextFunction } from 'express';
16
16
  import { v4 as uuid } from 'uuid';
17
+ import zod from 'zod';
17
18
  import type { GlobImportedWithMetas } from 'babel-plugin-glob-import';
18
19
 
19
20
  // Core
@@ -113,7 +114,7 @@ export type Hooks = {
113
114
 
114
115
  export type TControllerDefinition = {
115
116
  path?: string,
116
- validate?: (schema: any) => any,
117
+ schema?: zod.ZodSchema,
117
118
  controller: TServerController<ServerRouter>,
118
119
  }
119
120
 
package/types/icons.d.ts CHANGED
@@ -1 +1 @@
1
- export type TIcones = "long-arrow-right"|"times"|"solid/spinner-third"|"sack-dollar"|"bell"|"bullseye"|"project-diagram"|"user-friends"|"eye"|"lock"|"comments"|"phone"|"chalkboard-teacher"|"rocket"|"planet-ringed"|"brands/linkedin"|"chart-bar"|"user-circle"|"at"|"arrow-right"|"calendar-alt"|"paper-plane"|"crosshairs"|"plus-circle"|"comments-alt"|"user-shield"|"shield-alt"|"chart-line"|"money-bill-wave"|"star"|"link"|"file-alt"|"long-arrow-left"|"search"|"lightbulb"|"magnet"|"key"|"user"|"user-plus"|"mouse-pointer"|"thumbs-up"|"dollar-sign"|"times-circle"|"angle-up"|"angle-down"|"solid/crown"|"brands/discord"|"pen"|"plus"|"file"|"envelope"|"binoculars"|"check"|"arrow-left"|"info-circle"|"check-circle"|"exclamation-circle"|"meh-rolling-eyes"|"trash"|"solid/star"|"solid/star-half-alt"|"regular/star"|"chevron-left"|"cog"|"power-off"|"bars"|"usd-circle"|"users"|"home-alt"|"trophy"|"play"|"minus-circle"|"plane-departure"|"wind"|"question-circle"|"external-link"|"map-marker-alt"|"clock"|"arrow-to-bottom"|"ellipsis-h"|"building"|"unlink"|"bold"|"italic"|"underline"|"strikethrough"|"subscript"|"superscript"|"code"|"font"|"empty-set"|"horizontal-rule"|"page-break"|"image"|"table"|"poll"|"columns"|"sticky-note"|"caret-right"|"align-left"|"align-center"|"align-right"|"align-justify"|"indent"|"outdent"|"list-ul"|"check-square"|"h1"|"h2"|"h3"|"h4"|"list-ol"|"paragraph"|"quote-left"
1
+ export type TIcones = "times"|"solid/spinner-third"|"long-arrow-right"|"sack-dollar"|"bell"|"bullseye"|"project-diagram"|"user-friends"|"eye"|"lock"|"comments"|"phone"|"chalkboard-teacher"|"planet-ringed"|"brands/linkedin"|"rocket"|"user-circle"|"chart-bar"|"arrow-right"|"at"|"calendar-alt"|"paper-plane"|"crosshairs"|"plus-circle"|"comments-alt"|"user-shield"|"shield-alt"|"chart-line"|"money-bill-wave"|"star"|"link"|"file-alt"|"long-arrow-left"|"search"|"lightbulb"|"magnet"|"key"|"user"|"user-plus"|"mouse-pointer"|"thumbs-up"|"dollar-sign"|"times-circle"|"solid/crown"|"brands/discord"|"pen"|"plus"|"file"|"envelope"|"angle-up"|"angle-down"|"check-circle"|"magic"|"globe"|"industry"|"map-marker-alt"|"users"|"briefcase"|"solid/magic"|"angle-right"|"save"|"binoculars"|"info-circle"|"exclamation-circle"|"check"|"meh-rolling-eyes"|"trash"|"arrow-left"|"usd-circle"|"stream"|"home-alt"|"trophy"|"solid/star"|"solid/star-half-alt"|"regular/star"|"chevron-left"|"cog"|"power-off"|"bars"|"play"|"minus-circle"|"external-link"|"plane-departure"|"brands/whatsapp"|"wind"|"question-circle"|"arrow-to-bottom"|"clock"|"ellipsis-h"|"map-marker"|"language"|"calendar"|"fire"|"redo"|"building"|"bold"|"italic"|"underline"|"strikethrough"|"subscript"|"superscript"|"code"|"unlink"|"font"|"empty-set"|"horizontal-rule"|"page-break"|"image"|"table"|"poll"|"columns"|"sticky-note"|"caret-right"|"list-ul"|"check-square"|"h1"|"h2"|"h3"|"h4"|"list-ol"|"paragraph"|"quote-left"|"align-left"|"align-center"|"align-right"|"align-justify"|"indent"|"outdent"