@xyo-network/react-form-group 7.5.7 → 7.5.11

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.
Files changed (34) hide show
  1. package/dist/browser/FormGroup.d.ts +2 -2
  2. package/dist/browser/FormGroup.d.ts.map +1 -1
  3. package/dist/browser/InputError.d.ts +2 -2
  4. package/dist/browser/InputError.d.ts.map +1 -1
  5. package/dist/browser/control/FormControl.d.ts +2 -2
  6. package/dist/browser/control/FormControl.d.ts.map +1 -1
  7. package/dist/browser/control/FormControlBase.d.ts.map +1 -1
  8. package/dist/browser/control/accessor/ControlValueAccessorBase.d.ts +4 -3
  9. package/dist/browser/control/accessor/ControlValueAccessorBase.d.ts.map +1 -1
  10. package/dist/browser/index.mjs +116 -152
  11. package/dist/browser/index.mjs.map +1 -1
  12. package/package.json +55 -31
  13. package/src/FormGroup.ts +0 -227
  14. package/src/InputError.ts +0 -4
  15. package/src/context/Context.ts +0 -5
  16. package/src/context/Provider.tsx +0 -36
  17. package/src/context/State.ts +0 -8
  18. package/src/context/index.ts +0 -4
  19. package/src/context/use.ts +0 -5
  20. package/src/control/AbstractControl.ts +0 -127
  21. package/src/control/FormControl.ts +0 -31
  22. package/src/control/FormControlBase.ts +0 -84
  23. package/src/control/accessor/ControlValueAccessor.ts +0 -23
  24. package/src/control/accessor/ControlValueAccessorBase.ts +0 -191
  25. package/src/control/accessor/FormControlStatus.ts +0 -36
  26. package/src/control/accessor/ValidControlValue.ts +0 -1
  27. package/src/control/accessor/index.ts +0 -4
  28. package/src/control/index.ts +0 -4
  29. package/src/index.ts +0 -5
  30. package/src/storage/ArchivistFormGroupStorage.ts +0 -25
  31. package/src/storage/FormGroupStorage.ts +0 -8
  32. package/src/storage/index.ts +0 -2
  33. package/src/stories/test.stories.tsx +0 -17
  34. package/src/types/images.d.ts +0 -5
@@ -1,127 +0,0 @@
1
- import { forget } from '@xylabs/sdk-js'
2
-
3
- import type {
4
- ControlValueAccessorBaseEvents,
5
- FormControlStatus,
6
- ValidControlValue,
7
- } from './accessor/index.ts'
8
- import {
9
- ControlValueAccessorBase,
10
- DISABLED,
11
- INVALID,
12
- PENDING,
13
- VALID,
14
- } from './accessor/index.ts'
15
-
16
- export type AbstractControlEvents<TValue> = ControlValueAccessorBaseEvents<TValue> & {
17
- statusChanged: { status: FormControlStatus }
18
- }
19
-
20
- /**
21
- * This is the base class for `Control` classes (i.e. FormControl),
22
- *
23
- * It provides some of the shared behavior that all controls and groups of controls have, like
24
- * running validators, calculating status, and resetting state. It also defines the properties
25
- * that are shared between all sub-classes, like `value`, `valid`, and `dirty`. It shouldn't be
26
- * instantiated directly.
27
- *
28
- * NOTE: Heavily borrowed from Angular's AbstractControl:
29
- * https://github.com/angular/angular/blob/5dcdbfcba934a930468aec140a7183b034466bdf/packages/forms/src/model/abstract_model.ts
30
- */
31
- export class AbstractControl<TValue extends ValidControlValue = ValidControlValue> extends ControlValueAccessorBase<
32
- TValue,
33
- AbstractControlEvents<TValue>
34
- > {
35
- private _status: FormControlStatus | undefined = undefined
36
-
37
- constructor() {
38
- super({})
39
- }
40
-
41
- /**
42
- * A control is `disabled` when its `status` is `DISABLED`.
43
- *
44
- * Disabled controls are exempt from validation checks and
45
- * are not included in the aggregate value of their ancestor
46
- * controls.
47
- *
48
- * @returns True if the control is disabled, false otherwise.
49
- */
50
- /** @deprecated - disabled functionality not implemented */
51
- get disabled(): boolean {
52
- return this.status === DISABLED
53
- }
54
-
55
- /**
56
- * A control is `enabled` as long as its `status` is not `DISABLED`.
57
- *
58
- * @returns True if the control has any status other than 'DISABLED',
59
- * false if the status is 'DISABLED'.
60
- */
61
- get enabled(): boolean {
62
- return this.status !== DISABLED
63
- }
64
-
65
- /**
66
- * A control is `invalid` when its `status` is `INVALID`.
67
-
68
- *
69
- * @returns True if this control has failed one or more of its validation checks,
70
- * false otherwise.
71
- */
72
- get invalid(): boolean {
73
- return this.status === INVALID
74
- }
75
-
76
- /**
77
- * A control is `pending` when its `status` is `PENDING`.
78
- *
79
- * @returns True if this control is in the process of conducting a validation check,
80
- * false otherwise.
81
- */
82
- get pending(): boolean {
83
- return this.status == PENDING
84
- }
85
-
86
- /**
87
- * The raw value of the control.
88
- */
89
- get rawValue(): TValue {
90
- return this.value
91
- }
92
-
93
- /**
94
- * The current status of the control.
95
- */
96
- get status() {
97
- return this._status
98
- }
99
-
100
- /**
101
- * A control is `valid` when its `status` is `VALID`.
102
- *
103
- * @returns True if the control has passed all of its validation tests,
104
- * false otherwise.
105
- */
106
- get valid(): boolean {
107
- return this.status === VALID
108
- }
109
-
110
- setErrorAndValidity(error: string, status: FormControlStatus) {
111
- this.setError(error)
112
- this.setStatus(status)
113
- }
114
-
115
- setStatus(status: FormControlStatus) {
116
- if (this._status === status) return
117
-
118
- this._status = status
119
-
120
- const emit = async () => await this.emit('statusChanged', { status })
121
- forget(emit())
122
- }
123
-
124
- validate(): boolean {
125
- return true
126
- }
127
- }
@@ -1,31 +0,0 @@
1
- import type { EmptyObject } from '@xylabs/sdk-js'
2
-
3
- import type { AbstractControl } from './AbstractControl.ts'
4
-
5
- export type CursorPosition = {
6
- current: number | undefined
7
- previous: number | undefined
8
- }
9
-
10
- export interface FormControlValidator {
11
- blurError?: (value: string) => void
12
- changeError?: (value: string) => void
13
- // filter that supports an empty value
14
- pattern?: RegExp
15
- // filter that does not support an empty value
16
- patternStrict?: RegExp
17
- required?: boolean
18
- }
19
-
20
- export interface FormControlMask {
21
- cursorPosition: CursorPosition
22
- getCursorPosition?: () => number | undefined
23
- mask?: (value: string) => string
24
- onCursorChange?: (cursor: number | undefined) => void
25
- unmask?: (value: string) => string
26
- }
27
-
28
- export interface FormControl<TProps extends EmptyObject = EmptyObject> extends FormControlValidator, FormControlMask, AbstractControl {
29
- readonly name?: string
30
- props: TProps
31
- }
@@ -1,84 +0,0 @@
1
- import type { EmptyObject } from '@xylabs/sdk-js'
2
-
3
- import { AbstractControl } from './AbstractControl.ts'
4
- import type { SetOptions } from './accessor/index.ts'
5
- import type { CursorPosition, FormControl } from './FormControl.ts'
6
-
7
- const AllowAllRegex = /^.*$/s
8
-
9
- /**
10
- * A base class for form controls and their validation.
11
- */
12
- export abstract class FormControlBase<TProps extends EmptyObject = EmptyObject> extends AbstractControl implements FormControl {
13
- /**
14
- * The current and previous cursor position of the input element.
15
- */
16
- cursorPosition: CursorPosition = { current: undefined, previous: undefined }
17
-
18
- invalidMessage = 'Invalid input'
19
- pattern = AllowAllRegex
20
- patternStrict = AllowAllRegex
21
- props = {} as TProps
22
- required = false
23
-
24
- private _name: string | undefined = undefined
25
-
26
- constructor() {
27
- super()
28
- }
29
-
30
- get name() {
31
- return this._name
32
- }
33
-
34
- override get rawValue() {
35
- return this.unmask && this.value ? this.unmask(this.value) : this.value
36
- }
37
-
38
- blurError?(value: string): void | undefined
39
- changeError?(value: string): void
40
- getCursorPosition?(): number | undefined
41
- mask?(value: string): string
42
- onCursorChange: (cursor: number | undefined) => void = () => {}
43
-
44
- override setValue(value: string = '', setOptions: SetOptions) {
45
- // check for pattern validation
46
- if (this.unmask && this.pattern) {
47
- const unmasked = this.unmask(value)
48
- const match = RegExp(this.pattern).exec(unmasked)
49
- // set the new value before checking for errors
50
- super.setValue(this.mask ? this.mask(unmasked) : unmasked, setOptions)
51
- if (match) {
52
- // if the value matches the pattern, update the cursor position
53
- if (this.getCursorPosition) {
54
- const newCursor = this.getCursorPosition()
55
- this.onCursorChange(newCursor)
56
- }
57
- } else {
58
- // if no match, set the error and return to the previous value
59
- this.setValue(this.previousValue, setOptions)
60
- this.onCursorChange?.(this.cursorPosition.previous)
61
- }
62
- } else {
63
- // if no mask or pattern, just set the value
64
- super.setValue(value, setOptions)
65
- }
66
- // check for changeError validation after pattern validation
67
- this.changeError?.(value)
68
- }
69
-
70
- unmask?(value: string): string
71
-
72
- // For FormControls, validate is the same as running one of the error checking functions
73
- override validate(): boolean {
74
- const normalizedValue = this.value ?? ''
75
- // prefer the blurError function since validation assumes the user is done typing
76
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
77
- this.blurError ? this.blurError(normalizedValue) : this.changeError?.(normalizedValue)
78
- return !this.error
79
- }
80
-
81
- protected setName(name: string | undefined) {
82
- this._name = name
83
- }
84
- }
@@ -1,23 +0,0 @@
1
- import type { ValidControlValue } from './ValidControlValue.ts'
2
-
3
- export interface SetOptions {
4
- disableEmit?: boolean
5
- }
6
-
7
- export interface ControlSerializeSettings {
8
- sensitive?: boolean
9
- serializable?: boolean
10
- }
11
-
12
- export interface ControlValueAccessor<T = ValidControlValue> {
13
- readonly error: string
14
- readonly previousValue: T
15
- readonly serializeSettings: ControlSerializeSettings
16
- readonly touched: boolean
17
- readonly value: T
18
- registerOnChange(fn: (value: T) => void): void
19
- registerOnErrorChange(fn: (error: string) => void): void
20
- registerOnTouched(fn: (isTouched: boolean) => void): void
21
- setTouched(isTouched: boolean): void
22
- setValue(fieldValue: T, options?: SetOptions): void
23
- }
@@ -1,191 +0,0 @@
1
- import type { BaseParams } from '@xylabs/base'
2
- import { forget } from '@xylabs/sdk-js'
3
- import { ModuleBaseEmitter } from '@xyo-network/module-event-emitter'
4
-
5
- import type {
6
- ControlSerializeSettings, ControlValueAccessor, SetOptions,
7
- } from './ControlValueAccessor.ts'
8
- import type { ValidControlValue } from './ValidControlValue.ts'
9
-
10
- export type ControlValueAccessorBaseConfig = {
11
- disableEvents?: boolean
12
- }
13
-
14
- export const DefaultSetOptions: SetOptions = { disableEmit: false }
15
-
16
- export type ControlValueAccessorBaseEvents<TValue = ValidControlValue> = {
17
- errorChanged: { error: string }
18
- touchChanged: { touched: boolean }
19
- valueChanged: { value: TValue }
20
- }
21
-
22
- /**
23
- * The base class for control value accessors interface
24
- */
25
- export class ControlValueAccessorBase<
26
- TValue = ValidControlValue,
27
- TEventData extends ControlValueAccessorBaseEvents<TValue> = ControlValueAccessorBaseEvents<TValue>,
28
- >
29
- extends ModuleBaseEmitter<BaseParams, TEventData>
30
- implements ControlValueAccessor<TValue> {
31
- private _error: string = ''
32
-
33
- private _previousValue = undefined as TValue
34
-
35
- private _serializeSettings: ControlSerializeSettings = { sensitive: false, serializable: false }
36
-
37
- private _touched: boolean = false
38
-
39
- private _value = undefined as TValue
40
-
41
- private config: ControlValueAccessorBaseConfig
42
-
43
- constructor(config: ControlValueAccessorBaseConfig) {
44
- super({})
45
- this.config = config
46
- }
47
-
48
- /**
49
- * The error message for the control.
50
- */
51
- get error() {
52
- return this._error
53
- }
54
-
55
- /**
56
- * The "previous value" of the input element.
57
- */
58
- get previousValue() {
59
- return this._previousValue
60
- }
61
-
62
- /**
63
- * The serialize settings of the input element.
64
- */
65
- get serializeSettings() {
66
- return this._serializeSettings
67
- }
68
-
69
- /**
70
- * The "touched" state of the input element.
71
- */
72
- get touched() {
73
- return this._touched
74
- }
75
-
76
- /**
77
- * The current value of the input element.
78
- */
79
- get value() {
80
- return this._value
81
- }
82
-
83
- /**
84
- * The registered callback function called when a change or input event occurs on the input
85
- * element.
86
- */
87
- onChange = (_: TValue) => {}
88
-
89
- /**
90
- * Registers a function called when the control error changes.
91
- */
92
- onErrorChange: (error: string) => void = () => {}
93
-
94
- /**
95
- * The registered callback function called when a blur event occurs on the input element.
96
- */
97
- onTouched = (_isTouched: boolean) => {}
98
-
99
- /**
100
- * Registers a function called when the control value changes.
101
- * @param {(_value:ValidControlValue)=>void} fn
102
- * @returns void
103
- */
104
- registerOnChange(fn: (_value: TValue) => void): void {
105
- this.onChange = fn
106
- }
107
-
108
- /**
109
- * Registers a function called when the control error changes.
110
- * @param {(error:string)=>void} fn
111
- */
112
- registerOnErrorChange(fn: (error: string) => void) {
113
- this.onErrorChange = fn
114
- }
115
-
116
- /**
117
- * Registers a function called when the control is touched.
118
- * @param {(isTouched:boolean)=>void} fn
119
- * @returns void
120
- */
121
- registerOnTouched(fn: (isTouched: boolean) => void): void {
122
- this.onTouched = fn
123
- }
124
-
125
- /**
126
- * Sets the "touched" state of the input element.
127
- * @param {boolean} isTouched
128
- */
129
- setTouched(isTouched: boolean) {
130
- if (this.touched !== isTouched) {
131
- this._touched = isTouched
132
- this.onTouched(isTouched)
133
-
134
- if (this.config.disableEvents) return
135
- const emit = async () => await this.emit('touchChanged', { touched: isTouched })
136
- forget(emit())
137
- }
138
- }
139
-
140
- /**
141
- * Sets the "value" property on the input element.
142
- * @param {ValidControlValue} value
143
- * @returns void
144
- */
145
- setValue(value: TValue, options = DefaultSetOptions): void {
146
- this._previousValue = this._value
147
-
148
- const normalizedValue = value == null ? ('' as TValue) : value
149
-
150
- if (this.value !== normalizedValue) {
151
- this._value = normalizedValue
152
- this.onChange(normalizedValue)
153
-
154
- if (this.config.disableEvents || options.disableEmit) return
155
- const emit = async () => await this.emit('valueChanged', { value: normalizedValue })
156
- forget(emit())
157
- }
158
- }
159
-
160
- /**
161
- * Set the error message for the control.
162
- * @param {string} error
163
- */
164
- protected setError(error: string) {
165
- if (this.error !== error) {
166
- this._error = error
167
- this.onErrorChange(error)
168
-
169
- if (this.config.disableEvents) return
170
- const emit = async () => await this.emit('errorChanged', { error })
171
- forget(emit())
172
- }
173
- }
174
-
175
- /**
176
- * Sets the "previous value" of the input element.
177
- * @param {ValidControlValue} value
178
- * @returns void
179
- */
180
- protected setPreviousValue(value: TValue): void {
181
- this._previousValue = value
182
- }
183
-
184
- /**
185
- * Sets the serialize settings of the input element.
186
- * @param {ControlSerializeSettings} settings
187
- */
188
- protected setSerializeSettings(settings: ControlSerializeSettings) {
189
- this._serializeSettings = settings
190
- }
191
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * Reports that a control is valid, meaning that no errors exist in the input value.
3
- */
4
- export const VALID = 'VALID' as const
5
-
6
- /**
7
- * Reports that a control is invalid, meaning that an error exists in the input value.
8
- */
9
- export const INVALID = 'INVALID' as const
10
-
11
- /**
12
- * Reports that a control is pending, meaning that async validation is occurring and
13
- * errors are not yet available for the input value.
14
- */
15
- export const PENDING = 'PENDING' as const
16
-
17
- /**
18
- * Reports that a control is disabled, meaning that the control is exempt from ancestor
19
- * calculations of validity or value.
20
- */
21
- export const DISABLED = 'DISABLED' as const
22
-
23
- /**
24
- * A control can have several different statuses. Each
25
- * possible status is returned as a string literal.
26
- *
27
- * * **VALID**: Reports that a control is valid, meaning that no errors exist in the input
28
- * value.
29
- * * **INVALID**: Reports that a control is invalid, meaning that an error exists in the input
30
- * value.
31
- * * **PENDING**: Reports that a control is pending, meaning that async validation is
32
- * occurring and errors are not yet available for the input value.
33
- * * **DISABLED**: Reports that a control is
34
- * disabled, meaning that the control is exempt from ancestor calculations of validity or value.
35
- */
36
- export type FormControlStatus = typeof VALID | typeof INVALID | typeof PENDING | typeof DISABLED
@@ -1 +0,0 @@
1
- export type ValidControlValue = string | undefined
@@ -1,4 +0,0 @@
1
- export * from './ControlValueAccessor.ts'
2
- export * from './ControlValueAccessorBase.ts'
3
- export * from './FormControlStatus.ts'
4
- export * from './ValidControlValue.ts'
@@ -1,4 +0,0 @@
1
- export * from './AbstractControl.ts'
2
- export * from './accessor/index.ts'
3
- export * from './FormControl.ts'
4
- export * from './FormControlBase.ts'
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export * from './context/index.ts'
2
- export * from './control/index.ts'
3
- export * from './FormGroup.ts'
4
- export * from './InputError.ts'
5
- export * from './storage/index.ts'
@@ -1,25 +0,0 @@
1
- import type { ArchivistInstance } from '@xyo-network/archivist-model'
2
- import type { Payload } from '@xyo-network/payload-model'
3
-
4
- import type { FormGroupStorage } from './FormGroupStorage.ts'
5
-
6
- export class ArchivistFormGroupStorage implements FormGroupStorage {
7
- private archivist: ArchivistInstance
8
-
9
- constructor(archivist: ArchivistInstance) {
10
- this.archivist = archivist
11
- }
12
-
13
- async clear() {
14
- await this.archivist.clear?.()
15
- }
16
-
17
- async get() {
18
- const all = await this.archivist.all?.()
19
- return all.at(-1)
20
- }
21
-
22
- async insert(value: Payload) {
23
- await this.archivist.insert?.([value])
24
- }
25
- }
@@ -1,8 +0,0 @@
1
- import type { Promisable } from '@xylabs/sdk-js'
2
- import type { Payload } from '@xyo-network/payload-model'
3
-
4
- export interface FormGroupStorage<TValue extends Payload = Payload> {
5
- clear: () => Promisable<void>
6
- get: () => Promisable<TValue | undefined>
7
- insert: (state: TValue) => Promisable<void>
8
- }
@@ -1,2 +0,0 @@
1
- export * from './ArchivistFormGroupStorage.ts'
2
- export * from './FormGroupStorage.ts'
@@ -1,17 +0,0 @@
1
- /**
2
- * More to come...
3
- */
4
-
5
- import type { Meta, StoryFn } from '@storybook/react-vite'
6
- import React from 'react'
7
-
8
- export default { title: 'modules/form/test' } as Meta
9
-
10
- const Template: StoryFn<React.FC> = (args) => {
11
- return <div {...args}></div>
12
- }
13
-
14
- const Default = Template.bind({})
15
- Default.args = {}
16
-
17
- export { Default }
@@ -1,5 +0,0 @@
1
- declare module '*.png'
2
- declare module '*.jpg'
3
- declare module '*.svg'
4
- declare module '*.gif'
5
- declare module '*.webp'