1.0.2
A preact-based micro-framework for building token-based search bars
Lex
is a micro-framework for building token-based search bars. Rather than predefining how searches are performed, Lex
provides developers with the tools they need to define their own query language, and to develop unique UI components for constructing queries, thus supporting the widest possible set of potential use cases.
Lex is built internally with Preact, ensuring a minimal library size and compatibility with any modern SPA framework (VueJS, Aurelia, React, etc.) by remaining framework-neutral.
For current API documentation, please visit: https://unchartedsoftware.github.io/lex/
For demos of key features, visit: https://unchartedsoftware.github.io/lex/demo/
IMPORTANT: Node v14 required for local dev development. For current API documentation, please clone the project and run:
$ npm install $ npm run serve-docs
For demos of key features, refer to source in the demo
directory, while running:
$ npm install $ npm run serve-demos
Testing is done through Playwright based on the demo
examples included. Playwright is installed as a dependency but requires an additional step to pull the appropriate browsers for testing, to do this simply run:
$ npm install
$ npm run test:init
To run the tests simply start the demos
using npm run demos
and run the test:e2e
script in a separate terminal. If developing within VSCode you can use the official Playwright Plugin to run the tests within the IDE.
Testing is still WIP and a number of tests still need to be added.
In
Lex
, a search language is a finite-state machine.State
s represent "steps" towards successfully constructing a token through user-supplied values, and userstransition()
between them until they reach a terminalState
(one with no children).
Lex
attempts to provide an environment in which developers can craft their own search language, rather than enforcing one. Despite this goal, the following assumptions are made for the sake of improving user experience:
[TOKEN1 TOKEN2 TOKEN3]
)Lex
bar is interpeted as being joined by either AND
s or OR
s (i.e. [TOKEN1 & TOKEN2 & TOKEN3]
). This connective is not represented visually within the search bar, and thus is left up to the interpretation of the developer (however so far all existing apps using Lex
have chosen AND
).State
s - effectively, a path through the search language. Each State
stores one or more values and, together, the sequence represents a statement such as [Name, is, Sean]
, [Age, is not, 7]
or [Location, is, (Toronto,Victoria)]
.State
s can represent an OR
of values which, together with an overall choice of AND
connective, strongly encourage Conjunctive Normal Form as the basis for a search language.Defining a search language in Lex
is accomplished via method chaining. Let's start with a basic search language, which allows a user to select a column to search and supply a value. The state machine for this language consists of three states, with specific rules governing the transition between the root state and its two children:
Choose Column ----(if string)----> Enter String
\---(if numeric)---> Enter Number
Here is the implementation via Lex
:
import { Lex, TransitionFactory, ValueState, ValueStateValue, TextEntryState, NumericEntryState } from 'lex';;
// Lex.from() starts a subtree of the language
const language = Lex.from('columnName', ValueState, {
name: 'Choose a column to search',
suggestions: [
// ValueStates allow users to choose from a list
// of values (or potentially create their own).
// We set metadata "type"s on these options
// to help us make transition decisions later.
new ValueStateValue('Name', {type: 'string'}),
new ValueStateValue('Age', {type: 'numeric'})
]
}).branch(
Lex.from('value', TextEntryState, {
// transitions to this State are considered legal
// if the parent State's value had a metadata
// type === 'string'
...TransitionFactory.valueMetaCompare({type: 'string'})
}),
Lex.from('value', NumericEntryState, {
// Similarly, checking for parentVal.meta.type === 'numeric'
...TransitionFactory.valueMetaCompare({type: 'numeric'})
}),
);
Consuming the language is as accomplished via configuration when constructing a new instance of Lex
.
// Now we can instantiate a search bar that will respect this language.
const lex = new Lex({
language: language
// other configuration goes here
});
lex.render(document.getElementById('LexContainer'));
Lex
supports far more complex languages, validation rules, state types etc. than are shown in this brief example. Check out the demo
directory and API documentation for more details.
Lex
translates State
s from the search language into UI components as a user is creating or modifying a Token
. These components fall into two categories:
Token
. This is generally a text input that the user can type into to supply values to the current State
.Token
. Assistant
s provide an alternative, typically richer, mechanism for supplying values to the current State
.There must be one Builder
for each State
in a search language. Assistant
s are optional.
Lex
contains several built-in State
types, which are associated with default Builder
s and Assistant
s:
State | Default Builder | Default Assistant |
---|---|---|
LabelState |
LabelBuilder |
none |
ValueState |
ValueBuilder |
ValueAssistant |
RelationState |
ValueBuilder |
ValueAssistant |
TerminalState |
TerminalBuilder |
none |
TextEntryState |
ValueBuilder |
ValueAssistant |
TextRelationState |
ValueBuilder |
ValueAssistant |
NumericEntryState |
ValueBuilder |
ValueAssistant |
NumericRelationState |
ValueBuilder |
ValueAssistant |
CurrencyEntryState |
ValueBuilder |
ValueAssistant |
DateTimeEntryState |
DateTimeEntryBuilder |
DateTimeEntryAssistant |
DateTimeRelationState |
ValueBuilder |
ValueAssistant |
Two things are evident in this table:
State
types extend ValueState
, which is a powerful component supporting selecting a value from a list of suggestions, entering custom values, accepting multiple values, etc.State
type which is missing a direct Builder
or Assistant
will attempt to use the corresponding components for its superclass State
.Lex
may be extended, therefore, in the following ways (in descending order of likelihood):
State
s, extending existing State
s (i.e. extending ValueState
but using ValueBuilder
and ValueAssistant
)Assistant
s for existing State
s (i.e. implementing a custom drop-down UI for choosing dates and times)Builder
s for existing State
s (mostly for formatting "finished" Token
s in unique ways by overriding renderReadOnly()
)State
s, with custom Builder
s and Assistant
s. (i.e. implementing a GeoBoundsEntryState
with a custom Builder
, and an Assistant
featuring a map)The State
s, Builder
s and Assistant
s within the library are well-documented examples of how these extension types are accomplished, and exist as a reference for this purpose.
Overrides must be registered with Lex
before the search bar is rendered:
// ...
lex.registerBuilder(DateTimeEntryState, CustomDateTimeEntryBuilder);
lex.registerAssistant(CurrencyEntryState, CustomCurrencyEntryAssistant);
lex.render(document.getElementById('LexContainer'));
The following co-requisites must be part of your JS build in order to use Lex:
{
"element-resize-detector": "1.1.x", // developed against "1.1.15"
"preact": "8.x", // developed against: "8.5.2",
"moment-timezone": "0.5.x", // developed against "0.5.34"
"flatpickr": "4.6.x" // developed against: "4.6.3"
}
The following polyfills are required for use in IE and are not provided by this library:
Lex ships with both a compiled CSS stylesheet (lex.css
) and a raw SASS stylesheet (lex.scss
). If you wish to customize styles, you will need to include the raw SASS stylesheet in your build and override one or more of the following variables (shown here with their default values):
$lex-background: revert; // use the background color inherited from Bootstrap
$lex-border-color: revert; // use the border color inherited from Bootstrap
$lex-border-radius-base: 3px; // border radius for various things
$lex-highlight-color: #0097a7; // highlight color for various things
$lex-highlight-text-color: #fff; // color for text shown on top of a highlight-color background
$lex-danger-highlight-color: #d9534f; // highlight color for dangerous things
$lex-danger-highlight-text-color: #fff; // color for text shown on top of a danger-highlight-color background
$lex-line-height: 1.67; // base line height for lex tokens, etc.
$lex-token-padding: 2px; // padding for lex tokens
$lex-token-value-spacing: 0.3em; // spacing for token value inputs
$lex-token-background: #ededed; // background color for tokens
$lex-token-color: #555; // text color for tokens (inherit from Bootstrap)
$lex-token-hover-color: lighten($lex-token-color, 15%); // hover color for close button
$lex-token-border-color: darken($lex-token-background, 15%); // border color for a token
$lex-token-active-background: darken($lex-token-background, 15%); // background for active token components
$lex-token-input-border-color: transparent; // border for lex token text inputs
$lex-token-remove-button-color: lighten($lex-token-color, 45%); // hover color for remove button in multi-entry
$lex-token-remove-button-hover-color: darken($lex-token-remove-button-color, 15%); // text color for remove button in multi-entry
$lex-token-active-background: darken($lex-token-background, 15%); // background color for active region of a token. should lighten for dark theme
$lex-token-invalid-background: #e2a4e2; // background color for invalid region of token. should lighten for dark theme
$lex-assistant-background: #fff; // background color for assistant drop-down
$lex-assistant-border-color: $lex-token-border-color; // border color for assistant drop-down
$lex-assistant-header-background: $lex-token-background; // header background color for assistant drop-down
$lex-assistant-header-color: #8d8d8d; // header text color for assistant drop-down
API documentation for Lex follows, divided into sections.
Lex - A micro-framework for building search bars.
This class is an EventEmitter
and exposes the following events:
on('token start', () => {})
when the user begins to create or edit a token.on('token end', () => {})
when the user finishes creating or editing a token.on('token action', (tokenIdx, actionVkey, newModel, newUnboxedModel, oldActionVal) => {})
when the user triggers a token action.on('query changed', (newModel, oldModel, newUnboxedModel, oldUnboxedModel, nextTokenStarted) => {})
when query model changes.on('suggestions changed', (newModel, oldModel, newUnboxedModel, oldUnboxedModel) => {})
when suggestion model changes.on('validity changed', (newValidity, oldValidity) => {})
when validity of an active builder changes.Extends EventEmitter
Name | Description |
---|---|
config.language StateTemplate
|
The root state of the search language this bar will support. |
config.placeholder (string | undefined)
|
Placeholder text for the search bar (optional). |
config.container (string | DOMNode)
|
Container for Lex popups, such as
Assistants
.
|
config.proxiedEvents Array<string>
|
A list of keydown events to proxy from
Builder
s to
Assistant
s. If the active
Builder
does not consume said event, it will be sent to the active
Assistant
(if any).
['ArrowUp', 'ArrowDown', 'Tab', 'Enter']
by default.
|
config.defaultQuery Array<Object>
|
The default search state for this search box. Can either be an array of arrays of boxed or unboxed (basic type) values. |
config.tokenXIcon string
|
The default X icon for tokens (DOM string). |
config.multivalueDelimiterKey number
|
The JS key code of the delimiter which will notionally 'separate' multiple values in any visual representation of a multivalue state. 188 (',') by default. |
config.multivaluePasteDelimiter string
|
The characters which are supported as delimiters text which is pasted into a multivalue state. ',' by default. |
config.cssClass Array<string>
|
Add unique classes to the lex search bar and associated assistant |
config.cancelOnBlur boolean
|
Whether or not to cancel token creation/editing on blur. True by default. |
config.onAcceptSuggestion (function | undefined)
|
A callback called when the user presses "add" on a suggestion. A no-op by default (
(s, idx) => s
) but, if supplied, can be used to transform the incoming boxed suggestion, perform additional actions, etc. Return
null
to stop Lex from updating suggestions and query automatically, or return the suggestion (or a transformed version) to allow Lex to handle the rest.
|
config.onRejectSuggestion (function | undefined)
|
A callback called when the user presses "x" on a suggestion. A no-op by default (
(s, idx) => true
) but, if supplied, can be used to perform additional actions or stop Lex from auto-updating the suggestions and query (by returning
false
)
|
// Instantiate a new instance of lex and bind it to the page.
const lex = new Lex(language);
lex.render(document.getElementById('lex-container'));
// Override default builder/assistant associations
const lex = new Lex(language);
lex.registerBuilder(ValueState, MyCustomOptionBuilder);
Define a new search language.
(string)
The (optional) unique key used to store this state's value within a
Token
output object. If not supplied, this state won't be represented in the
Token
value.
StateTemplate
:
A reference to the new root
StateTemplate
, for chaining purposes to
.addChild()
.
import { Lex } from 'lex';
Lex.from('field', ValueState, {
name: 'Choose a field to search',
options:[
new ValueStateValue('Name', {type: 'string'}),
new ValueStateValue('Income', {type: 'number'})
]
}).to(...).to(...) // to() has the same signature as from()
Register a new component as the "builder" for a certain StateTemplate
type.
(Component)
A class extending
Component
, which can supply values to a
State
created from the
StateTemplate
.
Lex
:
A reference to
this
for chaining.
Register a new component as the "assistant" for a certain StateTemplate
type.
(Component)
A class extending
Component
, which can supply values to a
State
created from the
StateTemplate
.
Lex
:
A reference to
this
for chaining.
Register a new component as the "action button" for a certain Action
type.
(Component)
A class extending
Component
, which can supply values to an
Action
.
Lex
:
A reference to
this
for chaining.
Renders this instance of Lex to the DOM at a particular node.
(HTMLElement)
The target DOM node.
Unmounts this instance of Lex from the DOM.
Suggestion tokens.
(boolean
= true
)
If false, suppresses associated
'query changed'
event. Defaults to true.
Promise
:
Resolves when the attempt to rewrite the query is finished. This is
async
due to the fact that
State
s such as
ValueState
s might retrieve their suggestions asynchronously.
Focus the search box, and the active builder (if there is one).
Rewrite the query.
(boolean
= true
)
If false, suppresses associated
'query changed'
event. Defaults to true.
Promise
:
Resolves when the attempt to rewrite the query is finished. This is
async
due to the fact that
State
s such as
ValueState
s might retrieve their suggestions asynchronously.
A factory for a State
, which can be used to produce instances
from the provided configuration object.Also a builder for chaining
this StateTemplate
to children, creating a DAG of StateTemplate
s
which describes your search language.
(Class)
A
State
class that this factory will produce.
Recursively clones this StateTemplate
DAG, to retrieve an identical DAG of State
s,
populated with their defaultValue
s and ready to be traversed.
(State
= undefined
)
A reference to the concrete parent
State
. Do not set when calling - used internally for recursion.
State
:
A clone of the DAG rooted at this
StateTemplate
, with each node instanced as a
State
.
Add an Action
implication to this State
.
StateTemplate
:
A reference to the new child
State
, for chaining purposes.
Add a child to this StateTemplate
.
(string)
The (optional) unique key used to store this state's value within a
Token
output object. If not supplied, this state won't be represented in the
Token
value.
StateTemplate
:
A reference to the new child
State
, for chaining purposes.
Set the children of this StateTemplate
to the provided branches.
StateTemplate
:
A reference to this
StateTemplate
(not any of the child factories).
Describes a particular state in a state machine (DAG) which
represents the interactive build process for a token. The state
machine implied by a tree of State
s will be traversed
one state at a time (parent to child) by the user as they interact
with its visual representation, resulting in a sequence of state
values which constitute a valid "token" within your search language.
This class is meant to be extended to implement new state types.
State
supports a notion of boxed/unboxed values, where the
internal representation of the value is richer than the String
version
supplied by the user. Override boxValue
and unboxValue
to utilize
this functionality. By default, the internal representation and the
user-supplied one are the same (a string
), and no overriding is necessary.
Values should not be Array
s, but can be object
s (Array
s interfere
with internal multi-value handling).
this.value
always accepts/returns a boxed value. Where desired, the boxed and
unboxed versions of the value can be identical.
State
s support an archive for values, in order to facilitate multi-
value entry. Valid values may be pushed onto the archive, making room
for a new value entry to take place. The top archived value may also
be moved back to replace the current value.
This class is an EventEmitter
, exposing the following events:
on('value changed', (newVal, oldVal) => {})
when the internal value changes.on('value archived', () => {})
when a value is archived.on('value unarchived', () => {})
when a value is archived.on('preview value changed', (newVal, oldVal) => {})
when the internal preview value changes.on('unboxed value change attempted', (newUnboxedVal, oldUnboxedVal))
when a user attempts to change the unboxed value. If it cannot be boxed, it may not trigger value changed
.Extends EventEmitter
Name | Description |
---|---|
config.parent (State | undefined)
|
The parent state.
undefined
if this is a root.
|
config.name string
|
A useful label for this state - used for display purposes. |
config.vkey string
|
A key used to enter the value of this state into the value object of the containing machine. |
config.transition (Function | undefined)
|
A function which returns true if this state is the next child to transition to, given the value of its parent. Undefined if this is root. |
config.validate (Function | undefined)
|
A function which returns true iff this state has a valid value. Should throw an exception otherwise. |
config.defaultValue any
|
The default boxed value for this state before it has been touched. Can be undefined. Should not be an
Array
(but can be an
object
).
|
config.autoAdvanceDefault boolean
|
If a
defaultValue
is set and
autoAdvanceDefault
is true, this
State
auto-transition to the next
State
using its
defaultValue
.
|
config.readOnly boolean
|
This state is read only (for display purposes only) and should be skipped by the state machine. False by default. |
config.bindOnly boolean
|
This state is bind only (can be created programatically, but not by a user). False by default. |
config.hideLifecycleInteractions boolean
|
This state should not be presented with visual lifecycle interactions. False by default. |
config.multivalue boolean
|
Whether or not this state supports multi-value entry. |
config.multivalueLimit (number | undefined)
|
An optional limit on the number of values this state can contain. |
config.icon (string | Function)
|
A function which produces an icon suggestion (HTML
string
) for the containing
Token
, given the value of this state. May also supply an HTML
string
to suggest regardless of state value. The suggestion closest to the current valid state is used.
|
config.cssClasses Array<string>
|
One or more CSS classes which, when this
State
is transitioned to, will be applied to the containing
Token
. They will be removed if the machine is rewound before this
State
.
|
config.resetOnRewind boolean
|
This state should reset child states when rewound to during a token edit. False by default. |
class MyCustomState extends State {
constructor (config) {
super(config);
const {myCustomOption} = config;
// do something with myCustomOption
}
boxValue (userVal) {
// userVal is what a user might type to supply a value to this state
// TODO implement transform into richer internal representation
}
unboxValue (internalRepresentation) {
// TODO return a string representation of the richer internal representation.
}
}
Perform any asynchronous operations required to initialize this State
.
Override in subclasses to add asynchronous functionality to a State
.
(Array<any>
= []
)
The current boxed value of the containing
TokenStateMachine
(all
State
s up to and including this one).
((any | undefined))
The initial unboxed value which will be bound to this
State
.
Promise
:
A
Promise
which resolves when initialize completes successfully, rejecting otherwise.
Utilizes the validate
function to check value validity.
boolean
:
Returns
true
if this state is valid. Should throw an exception with information about validation error otherwise.
Called from a parent State
, this method utilizes the transition function
to determine whether or not a transition to this State
is valid given the parent's value.
(boolean
= false
)
All bind-only states are illegal transitions unless
ignoreBindOnly
is true.
boolean
:
Returns
true
iff a transition to this child is possible given the parent's value (and whether or not this
State
is
bindOnly
).
Getter for value
.
any
:
The current (boxed) value from this
State
.
Setter for value
. Clears any previewValue (if present).
(any)
Set a new (boxed) value for this
State
.
Getter for value
. Alias for this.value
.
any
:
The current (boxed) value from this
State
.
Setter for value
. Alias for this.value
. Clears any previewValue (if present).
(any)
Set a new (boxed) value for this
State
. Alias for this.value setter.
Getter for unboxedValue
.
any
:
The current (unboxed) value from this
State
.
Setter for unboxedValue
. Clears any previewValue (if present).
(any)
Set a new (unboxed) value for this
State
.
Getter for previewValue
- A value which is previewed as a suggestion for the user, without overwriting the value they've entered.
any
:
The current (boxed) previewValue from this
State
.
Setter for previewValue
- A value which is previewed as a suggestion for the user, without overwriting the value they've entered.
(any)
The new (boxed) previewValue for this
State
.
Getter for boxedPreviewValue
. Alias for this.previewValue
.
any
:
The current (boxed) previewValue from this
State
.
Setter for boxedPreviewValue
. Alias for this.previewValue
.
(any)
The new (boxed) previewValue for this
State
.
Getter for unboxedPreviewValue
- A value which is previewed as a suggestion for the user, without overwriting the value they've entered. Unboxed version.
string
:
The current (boxed) previewValue from this
State
.
Setter for previewValue
- A value which is previewed as a suggestion for the user, without overwriting the value they've entered. Unboxed version.
Getter for archive
d values.
Array<any>
:
The archive of valid values for this
State
.
Getter for archive
d values. Alias for this.archive
.
Array<any>
:
The archive of valid values for this
State
.
boolean
:
Returns true if the archive has room left, false otherwise. Does not validate.
Moves the current value to the archive, and resets the current value.
Remove all values from the archive.
An abstract superclass for a Component
which can be
used to construct a portion of a Token.
Subclasses generally implement renderInteractive
and focus
.
Extends Component
// See OptionBuilder for an example implementation.
If overridden, must be called via super.cleanupListeners()
.
Fires whenever the underlying machine or machine state changes.
If overridden, must be called via super.connectListeners()
.
Fires whenever the underlying machine or machine state changes.
If overridden, must be called via super.componentWillUnmount()
.
If overridden, must be called via super.componentWillMount()
.
Provide this builder with focus. Must be overriden in a subclass.
focus () {
if (this.textInput) this.textInput.focus();
}
Render the interactive version of this Builder
. Usually some form of <input>
.
Must override in subclasses.
(object)
Properties.
renderInteractive (props, {valid, readOnly}) {
return (
<input
ref={(input) => { this.textInput = input; }}
type="text"
disabled={readOnly}
className={valid ? 'token-input' : 'token-input invalid'}
/>
);
}
Receives functionality-related keydown
events, received at the search-bar level and
proxied to this component so that users can interact with the Assistant
via
keyboard controls without losing focus on their Builder
.
(Event)
The incoming event.
boolean
:
Returns
true
iff the event was consumed by this
Assistant
.
Getter for this.cancelOnBlur
.
Getter for this.isValid
.
boolean
:
Returns
true
iff this
State
is valid. Should throw an exception with information about validation error otherwise.
any
:
The (boxed) default value from the underlying
State
.
TokenStateMachine
:
The containing
TokenStateMachine
.
Getter for this.value
.
any
:
The current (boxed) value from the underlying
State
.
Setter for this.value
.
(any)
A new (boxed) value for the underlying
State
.
Getter for this.boxedValue
.
any
:
The current (boxed) value from the underlying
State
. An alias for this.value getter.
Setter for this.boxedValue
.
(any)
A new (boxed) value for the underlying
State
. Alias for this.value setter.
Getter for this.unboxedValue
.
any
:
The current (unboxed) value from the underlying
State
.
Setter for this.unboxedValue
.
(any)
A new (unboxed) value for the underlying
State
.
Getter for archive
d values.
Array<any>
:
The archive of valid values for the underlying
State
.
Richer interaction areas for building values.
These have no read-only mode, and are utilized as "drop-downs" to provide additional interactivity and visualization as users.
Subclasses generally implement delegateEvent
, renderInteractive
and focus
.
Extends Builder
// See OptionAssistant for an example implementation.
Called just before the machineState prop changes.
Called just after the machineState prop changes.
Children may set loading in order to visually indicate that the Assistant is performing an async operation.
(boolean)
Whether or not this Assistant is performing an async operation.
Render the interactive content of this Assistant
.
Must override in subclasses.
(object)
Properties.
VNode
:
The body content.
Convenient builders for constructing transition functions.
Transition to this state if the selected value from the parent state has one of the given keys.
object
:
A config object with key
transition
and the intended transition function, to be used directly or further customized.
// Transition to this child state if the parent option key is 'is', 'is like' or 'equals'
TransitionFactory.valueKeyIs('is', 'is like', 'equals')
Transition to this state if the selected option from the parent state does not match one of the given keys.
object
:
A config object with key
transition
and the intended transition function, to be used directly or further customized.
// Transition to this child state if the parent option key is not 'between'
TransitionFactory.valueKeyIsNot('between')
Transition to this state if the selected option from the parent state has metadata values which match
the given metadata object. Key/values present in toCompare
are (shallowly) compared against parentVal.meta
.
Any non-matching value invalidates the transition.
(object)
The metadata object.
object
:
A config object with key
transition
and the intended transition function, to be used directly or further customized.
TransitionFactory.valueMetaCompare({type: 'string'})
A state representing the selection of a value from a list of suggested values. Intended to facilitate both simple cases (such as selecting from a list of predefined options) and advanced ones (such as selecting from a list of dynamically updating suggestions).
By default, this state (and any extending classes) can be visually represented by ValueBuilder
and ValueAssistant
.
This class is an EventEmitter
and exposes the following events (in addition to State
's events):
on('fetching suggestions', () => {})
when a fetch for suggestions is triggered.on('fetching suggestions finished', (err) => {})
when a fetch for suggestions is finished, regardless of whether or not the suggestions changed. err
may be defined if something went wrong.on('suggestions changed', (newSuggestions, oldSuggestions) => {})
when the internal list of suggestions changes.on('typed text changed', (newText, oldText) => {})
when a user types text into the associated Builder.Extends State
(object)
A configuration object. Inherits all options from
State
, and adds additional elements.
Name | Description |
---|---|
config.overrideValidation (boolean | undefined)
|
Whether or not config.validate fully overrides
ValueState
's internal validation. If
false
, it works in conjunction with it.
false
by default.
|
config.fetchSuggestions (AsyncFunction | undefined)
|
A (required) function which is utilized for fetching suggestions via a hint (what the user has typed).
async (hint, context, formattedHint) => ValueStateValue[]
, executing in the scope of this
ValueState
, allowing access to its instance methods. If this is specified, config.suggestions should be null.
|
config.allowUnknown (boolean | undefined)
|
Allow user to supply unknown values (not from suggestions). Defaults to false. |
config.onUnknownValue (Function | undefined)
|
Optional hook (
(ValueStateValue) => ValueStateValue
) which, when a user enters an unknown
ValueStateValue
, allows for augmentation with things like metadata. Must return a new
ValueStateValue
, since
ValueStateValue
is immutable.
|
config.suggestionLimit (number | undefined)
|
A limit on the number of suggestions that will be shown at one time. Defaults to 5. |
config.units string
|
A textual label which represents "units" for the value state, such as "(h) or (kg)". |
Getter for suggestions
.
Setter for suggestions
.
(Array<ValueStateValue>)
A new set of suggestions.
boolean
:
Whether or not this value state allows the creation of unknown values.
number
:
The limit on the number of suggestions to display.
boolean
:
Whether or not any mechanism for supplying suggestions has been configured.
Transform a user-supplied value into a key
. Override in a subclass if the typedText
is
not directly usable as a key
(for example, to strip $ or whitespace).
(string)
What the user actually types/sees.
(Array<any>
= []
)
The current boxed value of the containing
TokenStateMachine
(all
State
s up to and including this one).
string
:
The key of a
ValueStateValue
within this
State
. Must not return null.
Transform a key
of a ValueStateValue
within this State
into
typedText
- what a user would actually see or type. Override in a subclass if the
typedText
is not directly interchangable with a key
(for example, to add $ or whitespace).
TIP: Don't format values that don't "make sense". Pass them through as-is and allow validation to catch them.
(Array<any>
= []
)
The current boxed value of the containing
TokenStateMachine
(all
State
s up to and including this one).
string
:
What the user actually types/sees.
Transform a key into an internal representation (ValueStateValue), where a key is the transformation of a user-supplied value by unformatUnboxedValue.
(string)
The user-supplied value.
ValueStateValue
:
An
ValueStateValue
instance.
Transforms an internal representation of a value (ValueStateValue) into a string key, where a key is the transformation of a user-supplied value by unformatUnboxedValue.
string
:
The string value of the
ValueStateValue
's key.
Can be called by a child class to trigger a refresh of suggestions based on a hint (what the
user has typed so far). Will trigger the async
function supplied to the constructor as config.fetchSuggestions
.
(string
= ''
)
What the user has typed, if anything, converted to a key by unformatUnboxedValue.
(object
= {}
)
The current boxed value of the containing
TokenStateMachine
(all
State
s up to and including this one).
(string
= ''
)
What the user has typed, if anything, but untouched by unformatUnboxedValue.
Promise
:
Resolves with the new list of options.
A rich value, which might be an object (such as a Date) or a basic type, along with associated metadata.
(string)
A string representation for this value. If two ValueStateValues are equal, their keys are equal (so they keys should be unique).
(any)
Whatever you want.
Name | Description |
---|---|
config.hidden boolean
|
If true, this
ValueStateValue
will never be suggested to the user.
|
config.displayKey (string | undefined)
|
A shorter representation of
key
displayed in read-only mode. Optional.
|
config.highlighted boolean
|
Whether or not this
ValueStateValue
is "highlighted" to the user. No more than one
ValueStateValue
should be highlighted within an
ValueState
.
|
This state supports the selection of a relation from a list of options.
Extends ValueState
(object)
A configuration object. Supports all of the parameters from
ValueState
and
StateTemplate
,
providing defaults for
name
and
options
.
config.options
should be a function returning
ValueStateValue
s.
This state supports the selection of a text relation from a list of options.
Extends RelationState
(object)
A configuration object. Supports all of the parameters from
ValueState
and
StateTemplate
,
providing defaults for
name
and
options
.
This state supports the selection of a numeric relation from a list of options.
Extends RelationState
(object)
A configuration object. Supports all of the parameters from
ValueState
and
StateTemplate
,
providing defaults for
name
and
options
.
This state supports the selection of a datetime relation from a list of options.
Extends RelationState
(object)
A configuration object. Supports all of the parameters from
ValueState
and
StateTemplate
,
providing defaults for
name
and
options
.
This state supports the entry of a String value, with possible auto-complete.
Extends ValueState
(object)
A configuration object.
This state supports the entry of a Number value, with possible auto-complete.
Extends ValueState
(object)
A configuration object. Supports all of the parameters from
ValueState
and
StateTemplate
,
providing defaults for
name
,
validate
(valid iff
!isNaN
) and
allowUnknown
(true).
This state supports the entry of a (stringified) Number value, with possible auto-complete.
Extends ValueState
(object)
A configuration object. Supports all of the parameters from
ValueState
and
StateTemplate
,
providing defaults for
name
,
validate
(valid iff
!isNaN
) and
allowUnknown
(true).
This state supports the entry of a Date/Time value, with support for a custom acceptable format.
Extends State
(object)
A configuration object. Supports all of the parameters from
State
,
providing defaults for
name
and
validate
.
Name | Description |
---|---|
config.format (string | undefined)
|
The acceptable format for a typed date. Defaults to
'YYYY/MM/DD'
.
|
config.timezone (string | undefined)
|
The assumed timezone for a typed date. Defaults to
'Etc/UTC'
.
|
config.enableTime boolean
|
If the date picker should display time picking UI. |
config.enableCalendar boolean
|
If the date picker should display the date picking UI. |
config.hilightedDate Date
|
The default selected date, defaults to today. |
config.time24hr boolean
|
If the date picker should display time picking UI in 24 hour format. |
Getter for timezone
.
string
:
The timezone that all entered dates will be interpreted in.
Getter for minDate
.
Date
:
The mininum date the picker will allow to be selected.
Getter for maxDate
.
Date
:
The maximum date the picker will allow to be selected.
Getter for enableTime
.
boolean
:
If this date picker should display time.
Getter for enableCalendar
.
boolean
:
If this date picker should display a calendar.
Getter for time24hr
.
boolean
:
If this date picker should display time in 24 hour format.
Getter for hilightedDate
.
Date
:
The date that the picker will initialize with as hilighted.
A non-interactive state providing a mechanism to add a textual label between two other builders.
By default, this state (and any extending classes) can be visually represented by LabelBuilder
.
Extends State
A visual interaction mechanism for supplying values
to a ValueState
. By default, this is registered as
the Builder
for ValueState
s.
Extends Builder
lex.registerBuilder(ValueState, ValueBuilder)
A visual representation of a LabelState
Extends Builder
lex.registerBuilder(LabelState, LabelBuilder)
A visual representation of a TerminalState
Extends Builder
lex.registerBuilder(TerminalState, TerminalBuilder)
A visual interaction mechanism for supplying values
to an DateTimeEntryState
. By default, this is registered as
the Builder
for DateTimeEntryState
s.
Extends Builder
lex.registerBuilder(DateTimeEntryState, DateTimeEntryBuilder)
A visual interaction mechanism for supplying values
to a ValueState
. By default, this is registered as
the Assistant
for ValueState
s.
Extends Assistant
lex.registerAssistant(ValueState, ValueAssistant)
A visual interaction mechanism for supplying values
to an DateTimeEntryState
. By default, this is registered as
the Assistant
for DatetimeEntryState
s.
Extends Assistant
lex.registerAssistant(DateTimeEntryState, DateTimeEntryAssistant)
A factory for an Action
, which can be used to produce instances
from the provided configuration object.
(Class)
An
Action
class that this factory will produce.
A concrete Action
, presented as a button only on completed Token
s,
which allows users to interact with Token
s in some way. Each Action
has its own internal value, and can only affect its own internal value.
Extends EventEmitter
Getter for value
.
any
:
The current internal value from this
Action
.
Setter for value
. Must be used when changing the internal value
in order to trigger associated events.
(any)
Set a new internal value for this
Action
.
Perform any asynchronous operations required to initialize this Action
.
Override in subclasses to add asynchronous functionality to a Action
.
(Array<any>
= []
)
The current boxed value of the containing
TokenStateMachine
(all
State
s).
Promise
:
A
Promise
which resolves when initialize completes successfully, rejecting otherwise.
A non-interactive, invisible state providing a mechanism for simulating an "optionally terminal" state. For example, an ValueState where certain values terminate the machine, but others do not.
Extends State
An EnumEntryStateValue represents an Enumeration value, with a string name and a numerical index.
Extends ValueStateValue
(any)
(any)
This state supports the entry of an enum Value, a string associated with a number, with possible auto-complete
config.enums
should be supplied as an array of EnumEntryStateValue
s.
For example, the enum value "hello"->1
would be represented as new EnumEntryStateValue(1, 'hello')
.
Extends ValueState
(object)
A configuration object. Supports most of the parameters from
ValueState
and
StateTemplate
,
providing defaults for
name
.
allowUnknown
is and must be false.
Possible Enumeration values must be fixed and provided via
config.enums
;
config.fetchSuggestions
and
config.suggestions
are not supported.
An TokenSuggestionStateValue represents an TokenSuggestionState value, with regexp pattern(s) and a function producing a full Token value which would be suggested if a regexp is matched.
Extends ValueStateValue
(any)
(Function)
A function which, receiving the match, returns the text to show a user describing this suggestion.
(AsyncFunction)
A function which, receiving the match, returns a
TokenStateMachine
boxedValue.
This state supports the suggestion of entire token values, with possible auto-complete.
Extends ValueState
(object)
A configuration object. Supports all of the parameters from
ValueState
and
StateTemplate
, providing defaults for
name
,
validate
and
allowUnknown
(false).
suggestions
and
fetchSuggestions
are not supported, and are supplanted by
config.tokenSuggestions
.
Interactions for Tokens.
Subclasses generally implement render
, onClick
.
Extends Component
If overridden, must be called via super.cleanupListeners()
.
Fires whenever the underlying action value changes.
If overridden, must be called via super.connectListeners()
.
Fires whenever the underlying action value changes.
If overridden, must be called via super.componentWillUnmount()
.
If overridden, must be called via super.componentWillMount()
.
Called just before a component, such as this Builder
or an Assistant
, requests a transition.
This is useful, for example, when an Assistant
wants to trigger a transition but needs its
associated Builder
to commit a typed value to state.unboxedValue
first.
Call from a subclass to request the state machine for the containing token to attempt transition.
Call from a subclass to request an immediate cancelling of the current state machine, and the creation of a brand new token.
(object)
The boxed token value to immediately create
Call from a subclass to request the state machine for the containing token to attempt archive a value.
Call from a subclass to request the state machine for the containing token to attempt unarchiving a value.
Call from a subclass to request the state machine for the containing token to attempt removal of a specific value from the archive.
(number)
The index of the value to remove.
Call from a subclass to request the state machine for the containing token to attempt removal of all values from the archive.
Call from a subclass to request the state machine for the containing token to attempt replacement of a specific archived value.
Call from a subclass to request the state machine for the containing token to attempt rewind.
Call from a subclass to request the state machine for the containing token to attempt rewind to this builder
Call from a subclass to inform containing components that this component has received focus. Since "focus" is not necessarily a literal concept (and could be triggered by a button press, or some other interaction), this is an artificial bubbling mechanism.
Call from a subclass to inform containing components that this Builder
is cancelling
input.
Call from a subclass to inform containing components that this component has been blurred. Since "focus" is not necessarily a literal concept (and could be triggered by a button press, or some other interaction), this is an artificial bubbling mechanism.
(Event)
A blur event from some DOM element within this Builder's visual representation.