Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
frama-c
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pub
frama-c
Commits
a7453338
Commit
a7453338
authored
4 years ago
by
Loïc Correnson
Browse files
Options
Downloads
Patches
Plain Diff
[dome] form documentation
parent
36ecd23f
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
ivette/src/dome/src/renderer/layout/form.tsx
+140
-29
140 additions, 29 deletions
ivette/src/dome/src/renderer/layout/form.tsx
with
140 additions
and
29 deletions
ivette/src/dome/src/renderer/layout/form.tsx
+
140
−
29
View file @
a7453338
...
...
@@ -3,6 +3,15 @@
/* --------------------------------------------------------------------------*/
/**
Form Fields are made of states and fields, arranged into a form page.
Field states are typically build with [[useState]] and [[useProperty]]
hooks, also you can also build them manually. All the provided hooks
can be used and composed with each other to build full feature states.
Form fields shall be arranged into sections and form pages to obtain a
wellformed layout.
@packageDocumentation
@module dome/layout/form
*/
...
...
@@ -79,6 +88,7 @@ function isValidArray(err: Error[]): boolean {
/* --- State Hooks ---*/
/* --------------------------------------------------------------------------*/
/** Create a local field state, like `React.useState()` does. */
export
function
useState
<
A
>
(
defaultValue
:
A
,
checker
?:
Checker
<
A
>
,
...
...
@@ -95,6 +105,7 @@ export function useState<A>(
return
[
value
,
error
,
setState
];
}
/** Provides a new state with a default value. */
export
function
useDefault
<
A
>
(
state
:
FieldState
<
A
|
undefined
>
,
defaultValue
:
A
,
...
...
@@ -103,23 +114,50 @@ export function useDefault<A>(
return
[
value
??
defaultValue
,
error
,
setState
];
}
/**
Coerces a state with defined value
into some with possibly undefined one.
*/
export
function
useDefined
<
A
>
(
state
:
FieldState
<
A
>
,
):
FieldState
<
A
|
undefined
>
{
const
[
value
,
error
,
setState
]
=
state
;
const
update
=
React
.
useCallback
(
(
newValue
:
A
|
undefined
,
newError
:
Error
)
=>
{
if
(
newValue
!==
undefined
)
{
setState
(
newValue
,
newError
);
}
},
[
setState
],
);
return
[
value
,
error
,
update
];
}
/**
Undefined value leads to an error.
@param onError - error message in case of undefined or invalid updates.
*/
export
function
useRequired
<
A
>
(
state
:
FieldState
<
A
>
,
onError
?:
string
,
):
FieldState
<
A
|
undefined
>
{
const
[
value
,
error
,
setState
]
=
state
;
const
cache
=
React
.
useRef
(
value
);
const
update
=
React
.
useCallback
(
(
newValue
:
A
|
undefined
,
newError
:
Error
)
=>
{
if
(
newValue
===
undefined
)
{
setState
(
cache
.
current
,
n
ew
Error
||
'
Required field
'
);
setState
(
cache
.
current
,
o
nError
||
'
Required field
'
);
}
else
{
setState
(
newValue
,
newError
);
}
},
[
cache
,
setState
],
},
[
cache
,
onError
,
setState
],
);
return
[
value
,
error
,
update
];
}
/**
Enrich the state with a local checker.
The local error, if any, has precedence over any error from updates.
*/
export
function
useChecker
<
A
>
(
state
:
FieldState
<
A
>
,
checker
?:
Checker
<
A
>
,
...
...
@@ -132,6 +170,23 @@ export function useChecker<A>(
return
[
value
,
error
,
update
];
}
/**
Transform a state `A` into a state `B` through converting functions.
Input and output functions shall be the inverse with each others.
In case an exception is raised during input conversion, state `B`
retains its previous value (or default value) but forwards
the translation error.
In case an exception is raised during output conversion, a local state
is maintained with the invalid `B` value until it is transformed into
a valid one.
@param input - converting function from `A` to `B`
@param output - converting function from `B` to `A`
*/
export
function
useFilter
<
A
,
B
>
(
state
:
FieldState
<
A
>
,
input
:
(
value
:
A
)
=>
B
,
...
...
@@ -173,6 +228,48 @@ export function useFilter<A, B>(
}
/**
Introduces a latency between local changes and propagated ones.
A transient local state is maintained during debounced updates, until
the last update is finally flushed.
*/
export
function
useLatency
<
A
>
(
state
:
FieldState
<
A
>
,
latency
?:
number
,
):
FieldState
<
A
>
{
const
[
value
,
error
,
setState
]
=
state
;
const
period
=
latency
??
0
;
const
[
localValue
,
setLocalValue
]
=
React
.
useState
(
value
);
const
[
localError
,
setLocalError
]
=
React
.
useState
(
error
);
const
[
dangling
,
setDangling
]
=
React
.
useState
(
false
);
const
update
=
React
.
useMemo
(()
=>
{
if
(
period
>
0
)
{
const
propagate
=
debounce
(
(
lateValue
:
A
,
lateError
:
Error
)
=>
{
setState
(
lateValue
,
lateError
);
setDangling
(
false
);
},
period
,
);
return
(
newValue
:
A
,
newError
:
Error
)
=>
{
setLocalValue
(
newValue
);
setLocalError
(
newError
);
setDangling
(
true
);
propagate
(
newValue
,
newError
);
};
}
setDangling
(
false
);
return
setState
;
},
[
period
,
setDangling
,
setState
,
setLocalValue
,
setLocalError
]);
return
[
dangling
?
localValue
:
value
,
dangling
?
localError
:
error
,
update
,
];
}
/**
Returns the state associated to a property of the input state.
*/
export
function
useProperty
<
A
,
K
extends
keyof
A
>
(
state
:
FieldState
<
A
>
,
property
:
K
,
...
...
@@ -189,26 +286,9 @@ export function useProperty<A, K extends keyof A>(
return
[
value
[
property
],
error
,
update
];
}
export
function
useLatency
<
A
>
(
state
:
FieldState
<
A
>
,
latency
?:
number
,
):
FieldState
<
A
>
{
const
[
initValue
,
initError
,
setState
]
=
state
;
const
period
=
latency
??
0
;
const
[
value
,
setValue
]
=
React
.
useState
(
initValue
);
const
[
error
,
setError
]
=
React
.
useState
(
initError
);
const
propagate
=
React
.
useMemo
(
()
=>
(
period
>
0
?
debounce
(
setState
,
period
)
:
setState
),
[
period
,
setState
],
);
const
update
=
React
.
useCallback
((
newValue
,
newError
)
=>
{
setValue
(
newValue
);
setError
(
newError
);
propagate
(
newValue
,
newError
);
},
[
setValue
,
setError
,
propagate
]);
return
[
value
,
error
,
update
];
}
/**
Returns the state associated to an index element of the input state.
*/
export
function
useIndex
<
A
>
(
state
:
FieldState
<
A
[]
>
,
index
:
number
,
...
...
@@ -228,7 +308,7 @@ export function useIndex<A>(
}
/* --------------------------------------------------------------------------*/
/* ---
Basics
---*/
/* ---
Form Filter Context
---*/
/* --------------------------------------------------------------------------*/
export
interface
FilterProps
{
...
...
@@ -244,10 +324,6 @@ export interface FilterProps {
export
interface
Children
{
children
:
React
.
ReactNode
}
/* --------------------------------------------------------------------------*/
/* --- Form Context ---*/
/* --------------------------------------------------------------------------*/
interface
FormContext
{
disabled
:
boolean
;
hidden
:
boolean
;
...
...
@@ -269,7 +345,10 @@ function useContext(props?: FilterProps): FormContext {
};
}
/** @category Form Containers */
/**
Allow to locally disable or hide all its children fields.
@category Form Containers
*/
export
function
FormFilter
(
props
:
FilterProps
&
Children
)
{
const
context
=
useContext
(
props
);
if
(
context
.
hidden
)
return
null
;
...
...
@@ -1006,6 +1085,36 @@ export function TimeField(props: TimeOrDateFieldProps) {
);
}
/* --------------------------------------------------------------------------*/
/* --- Color Field ---*/
/* --------------------------------------------------------------------------*/
/** @category Form Fields */
export
type
ColorFieldProps
=
FieldProps
<
string
|
undefined
>
;
/** @category Form Fields */
export
function
ColorField
(
props
:
ColorFieldProps
)
{
const
{
disabled
}
=
useContext
(
props
);
const
id
=
useHtmlFor
();
const
[
value
,
error
,
onChange
]
=
useTextInputField
(
props
,
600
);
return
(
<
Field
{
...
props
}
htmlFor
=
{
id
}
error
=
{
error
}
>
<
input
id
=
{
id
}
type
=
"color"
value
=
{
value
||
'
#ffffff
'
}
className
=
"dome-xForm-color-field"
disabled
=
{
disabled
}
onChange
=
{
onChange
}
/>
</
Field
>
);
}
/* --------------------------------------------------------------------------*/
/* --- Check Box Field ---*/
/* --------------------------------------------------------------------------*/
...
...
@@ -1091,8 +1200,9 @@ export interface SelectFieldProps extends FieldProps<string | undefined> {
Children must be standard `<option>` or `<optgroup>` elements.
@category Form Fields
*/
*/
export
function
SelectField
(
props
:
SelectFieldProps
)
{
const
{
disabled
}
=
useContext
(
props
);
const
id
=
useHtmlFor
();
const
[
value
,
error
,
setState
]
=
useChecker
(
props
.
state
,
props
.
checker
);
const
onChange
=
(
newValue
?:
string
)
=>
setState
(
newValue
,
undefined
);
...
...
@@ -1106,6 +1216,7 @@ export function SelectField(props: SelectFieldProps) {
<
SelectMenu
id
=
{
id
}
value
=
{
value
}
disabled
=
{
disabled
}
placeholder
=
{
placeholder
}
onChange
=
{
onChange
}
>
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment