# giu **Repository Path**: mirrors_guigrpa/giu ## Basic Information - **Project Name**: giu - **Description**: A collection of React components and utilities - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2020-11-23 - **Last Updated**: 2026-04-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Giu [![npm version](https://img.shields.io/npm/v/giu.svg)](https://www.npmjs.com/package/giu) An opinionated Swiss-army knife for building React application GUIs. Online demos: [an extremely compact one](http://guigrpa.github.io/giu/compact/) ([Material Design Lite version here](http://guigrpa.github.io/giu/material/)) and [an interactive version of this documentation](http://guigrpa.github.io/giu). ## Why? - Improvements over native HTML inputs: (optional) [state delegation](#inputs), [comprehensive validation](#input-validation), [native JS types and nullability](#input-value-types). - Support for **Server-Side Rendering**. - Support for **i18n**: error messages, date inputs, etc. - Love for detail: + [Stackable modals](#modals) with autofocus, default buttons, etc. + Sticky/retainable [notifications](#notifications) + [Keyboard shortcuts](#select) (cmd/ctrl-J, shift-up...) for options in selects and drop-down menus + Keyboard navigation for (almost) everything + Automatic scroll-into-view when inputs, even custom ones, are focused + Smart positioning of floating pickers (date and color inputs, drop-down menus, validation errors, etc.) + Ultra-customisable [date/time inputs](#dateinput) + Textarea with auto-resize + Uniform, lightweight styles that can easily be overriden via CSS * An extremely flexible [data table](#datatable) component + ... and a gorgeous [analog time picker](#dateinput)! - Simple theme settings: overall style (default vs. Material Design Lite)... - Easy creation of [hint screens](#hint-screens) with dynamically-positioned labels and arrows - Lots of [helper functions](#helpers) ## Installation Giu is intended to be bundled, e.g. with [*webpack*](https://webpack.github.io/). The examples under *packages/giu-examples/pages* are bundled with [Next.js](https://github.com/zeit/next.js/) and support SSR. Install it like this: ``` $ npm install --save-dev giu ``` Make sure you also install the required `peerDependencies` ([*react*](https://github.com/facebook/react)). Optionally, you may want to add: * [*moment*](https://github.com/moment/moment) — if you are going to use the DateInput component * [*material-design-lite*](https://github.com/google/material-design-lite) — if you are going to use the `mdl` theme (see example bundling for Webpack under *packages/giu-examples/pages/material.js*) You may also want to **add fonts to your bundle** (no longer included in Giu starting with v0.15). For example, the Hints component uses *Gloria Hallelujah* by default -- make sure you load it from Google Fonts, bundle it via something like [typeface-gloria-hallelujah](https://www.npmjs.com/package/typeface-gloria-hallelujah) (if you use Webpack), or just configure the Hints component with a different font. The same applies to *Font Awesome* (default icon font), *Roboto* and *Material Icons* (for the `mdl` theme). Once you've installed Giu, just `import { WhateverComponentYouNeed, maybeAlsoFunctions } from 'giu'`. The details on what is available can be found below. Note that many Giu components (including all inputs) require that you **include `` at (or near) the root level of your React tree**. No props are required. If you forget it, you'll see a warning in the console and those components will not work correctly. Other components you might want to add (if you use them): ``, ``, ``. More about them below. ## Inputs Giu provides a wide variety of inputs and several useful abstractions over native HTML native elements: state delegation (optional), comprehensive validation, JS types and nullability. You'll understand the benefits it brings with an example. Let's say you want to build a form that allows users to modify certain parameters of their registration profile, e.g. their age. With native HTML inputs, you'd use something like this: ```html this.setState({ age: Number(age) })} /> ``` It seems simple, right? But in reality you are handling a lot of stuff yourself: * You must keep track of the original `age` value in the profile (let's assume it was received as `this.props.age`), as well as the modified user value (`this.state.age`). * You must provide an `onChange` handler and keep your state up to date. * You must convert back and forth between the input's `string` value and your `number` attribute. * You must validate input contents before submitting the form. You *could* use Giu in a similar way: ```html this.setState({ age })} /> ``` This approach follows *The React Way™*, but we're already seeing a first benefit: the `onChange` handler will be called (in addition to the native event) with the *converted* input value: either a number or `null`; no need to do the conversion ourselves. But we can further improve on this: ```html // alternatively: { this.refAge = c; }} ... /> ``` What's happened here? We only pass the original age as `value`, but we delegate keeping track of the value entered by the user. We also drop the `onChange` handler and add some `validators` (see [details below](#input-validation)). When the time comes to submit the form, we can do: ```js onClickSubmit() { this.refs.age.validateAndGetValue().then(age => { ... }) } ``` The promise returned by `validateAndGetValue()` will either resolve with the current value or reject if validation fails. ### Input value types Most HTML inputs can only hold strings. Giu inputs provide you with JS types and allow `null` values by default (include the `required` flag to change that): | Components | JS type | | --- | --- | | TextInput, PasswordInput, Textarea | *string* | | NumberInput, RangeInput | *number* | | Checkbox | *boolean* | | DateInput | *Date* (see full range of date/time possibilities below) | | Select, RadioGroup | *any* (depends on the values specified in the `items` prop, see below) | | ColorInput | *string* (e.g. `rgba(173, 163, 120, 0.62)`) | | FileInput | *File* | ### Input validation #### Predefined validators Some validators are enabled by default: ```html // Shows an error if the provided value is an invalid date. // Will NOT complain if left blank; by default, Giu inputs can be left blank. ``` Validation occurs automatically when the input loses focus (i.e. on `blur`). You can also trigger it imperatively by calling `validateAndGetValue()` (see [Imperative API](#imperative-api)). Enabling additional validators is easy: ```html // Shows an error if left blank ('is required') // OR if the format is not valid ('must be a valid date...'). // Shows an error only if a value is specified but it's not valid. ``` Here is the list of predefined validators: ```js // Generic isRequired() // same as the 'required' attribute, but allowing customisation isEqualTo(password, 'password') isOneOf(['rabbit', 'cow', 'eagle']) // Strings hasAtLeastChars(5) hasAtMostChars(20) hasLengthWithinRange(5, 20) isEmail() isUrl() matchesPattern(/[-+]?[0-9]*\.?[0-9]+/) // Numbers isNumber() isGreaterThanOrEqual(0) // or: isGte(0) isLowerThanOrEqual(1000) // or: isLte(1000) isWithinRange(0, 1000) // Dates and times isDate() ``` As we saw above, some of these validators are automatically enabled for certain components, e.g. `isDate()` in DateInputs and `isNumber()` in NumberInputs. However, you can include them in your `validators` list for customisation (e.g. i18n), as you'll see next. #### Custom validators Customise a predefined validator by passing it an additional argument upon instantiation. This argument can be a string or a function returning the desired error message (e.g. for i18n) based on the following arguments: * Default error message * Current (internal) input value * Extra context, including the validator arguments (e.g. the `min` and `max` values for `isWithinRange`) and additional information (e.g. the expected format `fmt` for date/time values). Some examples: ```html // Override the message for the `isEmail` validator // Override the message for the `required` validator // Specify a function to further customise/translate your message import i18n from 'mady'; // a translation function i18n("'{VALUE}' is not a valid email address", { VALUE })), ]} /> // The error message function may use the extra context parameter: `follow this format: ${fmt}`), ]} /> i18n('must be >= {MIN}', { MIN: min })), ]} /> ``` You can also create your own validators, which can be synchronous (returning an error message) or asynchronous (returning a promise of an error message) and should have this signature: * **value** *any?*: the current internal value of the input component * **props** *object*: the input component's props (including default props) * **context** *object?*: additional validator context provided by certain components. For example, `DateInput` injects the `moment` object via context * **Returns** *Promise(string?)|string?*: error message A couple of examples: ```html // A custom sync validator val.toLowerCase() === 'unicorn' ? undefined : 'must be a \'unicorn\'' ]} /> // A custom async validator new Promise((resolve, reject) => setTimeout(() => val.toLowerCase() === 'unicorn' ? resolve() : resolve('checked the database; must be a \'unicorn\'') , 1000) ), ]} /> ``` ### Imperative API Giu generally follows *The React Way™*. In some particular cases, however, you may need or prefer a more imperative style: 1. Validate and fetch an input value before submitting a form 2. Move focus to an input, or away from it 3. Set an input's value (without affecting the original, reference value in the `value` prop) or revert the input state to the `value` prop You have already seen how to accomplish task 1, via a direct component call. Assuming you keep a `ref` to the input component: ```js async onClickSubmit() { const age = await this.refAge.validateAndGetValue(); // ... } ``` Tasks 2 and 3 above are also managed imperatively: ```js // Focus/blur on an input this.refAge.focus(); this.refAge.blur(); // Set the input's value (without touching the original value in props) this.refAge.setValue(23); // Revert the input's value this.refAge.revert(); ``` ### Common input props * Basic (see also the [introduction to inputs](#inputs)): * **value** *any?*: either the original value to be modified by the user, or the current input value (if you want to manage state yourself). See also the list of [input value types](#input-value-types) * **onChange** *function?*: include it if you want to manage state yourself, or if you just want to be informed about user changes * **onFocus** *function?* * **onBlur** *function?* * **disabled** *boolean?*: prevents the input from being interacted with; also affects styles * Validation-related (see also [input validation](#input-validation)): * **required** *boolean?*: synonym for the `isRequired()` validator * **validators** *array(object|function)?*: objects are used for predefined validators, whereas functions are used for custom ones * **noErrors** *boolean?*: ignore validation altogether * Float-related (for all inputs with floating pickers, e.g. Select, DateInput, ColorInput): * **floatPosition** *string(`above`|`below`)?*: if unspecified, a suitable position is selected algorithmically * **floatAlign** *string(`left`|`right`)? = `left`*: if unspecified, a suitable position is selected algorithmically * Error-float-related: * **errorPosition** *string(`above`|`below`)?*: if unspecified, Giu chooses `below` except if `floatPosition` is specified (it then chooses the opposite position) * **errorAlign** *string(`left`|`right`)? = `left`* ### TextInput, PasswordInput, NumberInput, RangeInput, Textarea Props: ```js type PublicProps = { ...$Exact, // common to all inputs (check the docs!) className?: string, id?: string, disabled?: boolean, skipTheme?: boolean, vertical?: boolean, // only for RangeInput // all others are passed through to the `input` unchanged }; ``` ### Checkbox Props: ```js type PublicProps = { ...$Exact, // common to all inputs (check the docs!) className?: string, id: string, label?: React.Node, // React components to be included in the checkbox's `label` element disabled?: boolean, skipTheme?: boolean, }; ``` ### DateInput Shown below are some examples of DateInput, one of Giu's most versatile components: date/time/date-time modes, with or without drop-down pickers, inline pickers, digital/analogue time picker, disabled style... Not shown: keyboard navigation, clipboard events. ![DateInput screenshots](https://raw.githubusercontent.com/guigrpa/giu/master/docsPrivate/DateInputs.png) If you use [*moment*](https://github.com/moment/moment), your date picker and date/time formats will be automatically translated when you choose a different locale, e.g. `moment.locale('es')`: ![Translated date picker](https://raw.githubusercontent.com/guigrpa/giu/master/docsPrivate/DateInput-i18n.png) Props: ```js type PublicProps = { ...$Exact, // common to all inputs (check the docs!) className?: string, id?: string, type?: PickerType, // see below (default: 'dropDownPicker') // Whether Giu should check for iOS in order to simplify certain components // (e.g. do not use analogue time picker) -- default: true checkIos?: boolean, disabled?: boolean, placeholder?: string, // when unspecified, the expected date/time format will be used date?: boolean, // whether the date is part of the value (default: true) time?: boolean, // whether the time is part of the value (default: false) // Whether the time picker should be analogue (traditional clock) // or digital (list) (default: true) analogTime?: boolean, // (default: true [in iOS: false]) seconds?: boolean, // whether seconds should be included in the time value (default: false) // UTC mode; by default, it is `true` *unless* `date` and `time` are both `true`. // In other words, local time is only used by default if both `date` and `time` are enabled utc?: boolean, // (default: !(date && time)) todayName?: string, // label for the *Today* button (default: 'Today') // Current language (used just for force-render). // Use it to inform Giu that you have changed `moment`'s language. lang?: string, floatPosition?: FloatPosition, floatAlign?: FloatAlign, skipTheme?: boolean, }; type PickerType = 'native' | 'onlyField' | 'inlinePicker' | 'dropDownPicker'; ``` ### Select Shown below are some examples of Select and its features: `native` and custom (`inlinePicker`|`dropDownPicker`) versions, keyboard shortcuts, disabled style. Not shown: keyboard navigation, clipboard events, automatic scrolling. ![Select screenshots](https://raw.githubusercontent.com/guigrpa/giu/master/docsPrivate/Selects2.png) *Recommendation: use `dropDownPicker` for performance, especially if you have hundreds/thousands of Selects with many options: `native` Selects attach all of their `option` subelements to the page, whereas custom Selects only do that when the dropdown is shown.* Props: ```js export type SelectProps = { // Both SelectCustom and SelectNative // ---------------------------------- className?: string, id?: string, type: SelectPickerType, // see below (default: 'native') // Items with the following attributes: // - **value** *any*: any value that can be converted to JSON. Values should be unique // - **label** *string*: descriptive string that will be shown to the user // - **keys** *array(string)?*: keyboard shortcuts for this option, e.g. // `mod+a` (= `cmd+a` in OS X, `ctrl+a` in Windows), `alt+backspace`, `shift+up`... // **Only supported in non-native Selects** items: Array, lang?: string, // current language (used just for force-render). // Apart from its use for [validation](#input-validation), // enabling this flag disables the addition of a `null` option to the `items` list required?: boolean, disabled?: boolean, // SelectCustom only // ----------------- children?: any, onClickItem?: Function, onCloseFloat?: Function, floatPosition?: FloatPosition, floatAlign?: FloatAlign, // When enabled, two different visual styles are applied // to an item depending on whether it is just *hovered* or also *selected*. If disabled, // a single style is used to highlight the selected or the hovered item twoStageStyle?: boolean, }; export type SelectPickerType = 'native' | 'inlinePicker' | 'dropDownPicker'; ``` You can also include a separator between `items` by including the special `LIST_SEPARATOR` item (**only in non-native Selects**): ```js import { Select, LIST_SEPARATOR } from 'giu';