diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2023-05-12 17:42:09 -0300 |
---|---|---|
committer | (quasar) nebula <qznebula@protonmail.com> | 2023-05-13 12:48:36 -0300 |
commit | 6ea74c268a12325296a1d2e7fc31b02030ddb8bc (patch) | |
tree | 5da94d93acb64e7ab650d240d6cb23c659ad02ca /ui | |
parent | e783bcf8522fa68e6b221afd18469c3c265b1bb7 (diff) |
use ESM module syntax & minor cleanups
The biggest change here is moving various element classes under more scope-specific directories, which helps to avoid circular dependencies and is just cleaner to navigate and expand in the future. Otherwise this is a largely uncritical port to ESM module syntax! There are probably a number of changes and other cleanups that remain much needed. Whenever I make changes to tui-lib it's hard to believe it's already been <INSERT COUNTING NUMBER HERE> years since the previous time. First commits are from January 2017, and the code originates a month earlier in KAaRMNoD!
Diffstat (limited to 'ui')
-rw-r--r-- | ui/controls/Button.js (renamed from ui/form/Button.js) | 8 | ||||
-rw-r--r-- | ui/controls/FocusBox.js (renamed from ui/form/FocusBox.js) | 6 | ||||
-rw-r--r-- | ui/controls/Form.js (renamed from ui/form/Form.js) | 6 | ||||
-rw-r--r-- | ui/controls/ListScrollForm.js (renamed from ui/form/ListScrollForm.js) | 13 | ||||
-rw-r--r-- | ui/controls/TextInput.js (renamed from ui/form/TextInput.js) | 12 | ||||
-rw-r--r-- | ui/controls/index.js | 16 | ||||
-rw-r--r-- | ui/dialogs/CancelDialog.js (renamed from ui/form/CancelDialog.js) | 13 | ||||
-rw-r--r-- | ui/dialogs/ConfirmDialog.js (renamed from ui/form/ConfirmDialog.js) | 13 | ||||
-rw-r--r-- | ui/dialogs/Dialog.js (renamed from ui/Dialog.js) | 9 | ||||
-rw-r--r-- | ui/dialogs/FilePickerForm.js (renamed from ui/tools/FilePickerForm.js) | 23 | ||||
-rw-r--r-- | ui/dialogs/OpenFileDialog.js (renamed from ui/tools/OpenFileDialog.js) | 20 | ||||
-rw-r--r-- | ui/dialogs/index.js | 16 | ||||
-rw-r--r-- | ui/index.js | 4 | ||||
-rw-r--r-- | ui/presentation/HorizontalBox.js (renamed from ui/HorizontalBox.js) | 4 | ||||
-rw-r--r-- | ui/presentation/Label.js (renamed from ui/Label.js) | 6 | ||||
-rw-r--r-- | ui/presentation/Pane.js (renamed from ui/Pane.js) | 10 | ||||
-rw-r--r-- | ui/presentation/Sprite.js (renamed from ui/Sprite.js) | 6 | ||||
-rw-r--r-- | ui/presentation/WrapLabel.js (renamed from ui/WrapLabel.js) | 9 | ||||
-rw-r--r-- | ui/presentation/index.js | 15 | ||||
-rw-r--r-- | ui/primitives/DisplayElement.js (renamed from ui/DisplayElement.js) | 13 | ||||
-rw-r--r-- | ui/primitives/Element.js (renamed from ui/Element.js) | 4 | ||||
-rw-r--r-- | ui/primitives/FocusElement.js (renamed from ui/form/FocusElement.js) | 4 | ||||
-rw-r--r-- | ui/primitives/Root.js (renamed from ui/Root.js) | 26 | ||||
-rw-r--r-- | ui/primitives/index.js | 11 |
24 files changed, 159 insertions, 108 deletions
diff --git a/ui/form/Button.js b/ui/controls/Button.js index 46329a6..5be2b2a 100644 --- a/ui/form/Button.js +++ b/ui/controls/Button.js @@ -1,9 +1,9 @@ -const ansi = require('../../util/ansi') -const telc = require('../../util/telchars') +import {FocusElement} from 'tui-lib/ui/primitives' -const FocusElement = require('./FocusElement') +import * as ansi from 'tui-lib/util/ansi' +import telc from 'tui-lib/util/telchars' -module.exports = class Button extends FocusElement { +export default class Button extends FocusElement { // A button. constructor(text) { diff --git a/ui/form/FocusBox.js b/ui/controls/FocusBox.js index 69b5bf5..64f84c9 100644 --- a/ui/form/FocusBox.js +++ b/ui/controls/FocusBox.js @@ -1,8 +1,8 @@ -const ansi = require('../../util/ansi') +import {FocusElement} from 'tui-lib/ui/primitives' -const FocusElement = require('./FocusElement') +import * as ansi from 'tui-lib/util/ansi' -module.exports = class FocusBox extends FocusElement { +export default class FocusBox extends FocusElement { // A box (not to be confused with Pane!) that can be selected. When it's // selected, it applies an invert effect to its children. (This won't work // well if you have elements inside of it that have their own attributes, diff --git a/ui/form/Form.js b/ui/controls/Form.js index 451baa4..921096a 100644 --- a/ui/form/Form.js +++ b/ui/controls/Form.js @@ -1,8 +1,8 @@ -const telc = require('../../util/telchars') +import telc from 'tui-lib/util/telchars' -const FocusElement = require('./FocusElement') +import {FocusElement} from 'tui-lib/ui/primitives' -module.exports = class Form extends FocusElement { +export default class Form extends FocusElement { constructor() { super() diff --git a/ui/form/ListScrollForm.js b/ui/controls/ListScrollForm.js index 78c376f..3f75599 100644 --- a/ui/form/ListScrollForm.js +++ b/ui/controls/ListScrollForm.js @@ -1,11 +1,12 @@ -const ansi = require('../../util/ansi') -const telc = require('../../util/telchars') -const unic = require('../../util/unichars') +import * as ansi from 'tui-lib/util/ansi' +import telc from 'tui-lib/util/telchars' +import unic from 'tui-lib/util/unichars' -const DisplayElement = require('../DisplayElement') -const Form = require('./Form') +import {DisplayElement} from 'tui-lib/ui/primitives' -module.exports = class ListScrollForm extends Form { +import Form from './Form.js' + +export default class ListScrollForm extends Form { // A form that lets the user scroll through a list of items. It // automatically adjusts to always allow the selected item to be visible. // Unless disabled in the constructor, a scrollbar is automatically displayed diff --git a/ui/form/TextInput.js b/ui/controls/TextInput.js index 78d3b6d..1a32605 100644 --- a/ui/form/TextInput.js +++ b/ui/controls/TextInput.js @@ -1,10 +1,10 @@ -const ansi = require('../../util/ansi') -const unic = require('../../util/unichars') -const telc = require('../../util/telchars') +import {FocusElement} from 'tui-lib/ui/primitives' -const FocusElement = require('./FocusElement') +import * as ansi from 'tui-lib/util/ansi' +import telc from 'tui-lib/util/telchars' +import unic from 'tui-lib/util/unichars' -module.exports = class TextInput extends FocusElement { +export default class TextInput extends FocusElement { // An element that the user can type in. constructor() { @@ -142,4 +142,6 @@ module.exports = class TextInput extends FocusElement { get value() { return this.getDep('value') } set value(v) { return this.setDep('value', v) } + get cursorIndex() { return this.getDep('cursorIndex') } + set cursorIndex(v) { return this.setDep('cursorIndex', v) } } diff --git a/ui/controls/index.js b/ui/controls/index.js new file mode 100644 index 0000000..e99add1 --- /dev/null +++ b/ui/controls/index.js @@ -0,0 +1,16 @@ +// +// Import mapping: +// +// primitives -> +// Button +// FocusBox +// TextInput +// +// Form -> ListScrollForm +// + +export {default as Button} from './Button.js' +export {default as FocusBox} from './FocusBox.js' +export {default as Form} from './Form.js' +export {default as ListScrollForm} from './ListScrollForm.js' +export {default as TextInput} from './TextInput.js' diff --git a/ui/form/CancelDialog.js b/ui/dialogs/CancelDialog.js index 21ff6df..9069d43 100644 --- a/ui/form/CancelDialog.js +++ b/ui/dialogs/CancelDialog.js @@ -1,13 +1,10 @@ -const telc = require('../../util/telchars') +import {Button, Form} from 'tui-lib/ui/controls' +import {Label, Pane} from 'tui-lib/ui/presentation' +import {FocusElement} from 'tui-lib/ui/primitives' -const FocusElement = require('./FocusElement') +import telc from 'tui-lib/util/telchars' -const Button = require('./Button') -const Form = require('./Form') -const Label = require('../Label') -const Pane = require('../Pane') - -module.exports = class ConfirmDialog extends FocusElement { +export default class CancelDialog extends FocusElement { // A basic cancel dialog. Has one buttons, cancel, and a label. // The escape (esc) key can be used to exit the dialog (which sends a // 'cancelled' event, as the cancel button also does). diff --git a/ui/form/ConfirmDialog.js b/ui/dialogs/ConfirmDialog.js index 230230d..c0bcfae 100644 --- a/ui/form/ConfirmDialog.js +++ b/ui/dialogs/ConfirmDialog.js @@ -1,13 +1,10 @@ -const telc = require('../../util/telchars') +import {Button, Form} from 'tui-lib/ui/controls' +import {Label, Pane} from 'tui-lib/ui/presentation' +import {FocusElement} from 'tui-lib/ui/primitives' -const FocusElement = require('./FocusElement') +import telc from 'tui-lib/util/telchars' -const Button = require('./Button') -const Form = require('./Form') -const Label = require('../Label') -const Pane = require('../Pane') - -module.exports = class ConfirmDialog extends FocusElement { +export default class ConfirmDialog extends FocusElement { // A basic yes/no dialog. Has two buttons, confirm/cancel, and a label. // The escape (esc) key can be used to exit the dialog (which sends a // 'cancelled' event, as the cancel button also does). diff --git a/ui/Dialog.js b/ui/dialogs/Dialog.js index 0b77b12..19565f5 100644 --- a/ui/Dialog.js +++ b/ui/dialogs/Dialog.js @@ -1,10 +1,9 @@ -const FocusElement = require('./form/FocusElement') +import {Pane} from 'tui-lib/ui/presentation' +import {FocusElement} from 'tui-lib/ui/primitives' -const Pane = require('./Pane') +import telc from 'tui-lib/util/telchars' -const telc = require('../util/telchars') - -module.exports = class Dialog extends FocusElement { +export default class Dialog extends FocusElement { // A simple base dialog. // // Emits the 'cancelled' event when the cancel key (escape) is pressed, diff --git a/ui/tools/FilePickerForm.js b/ui/dialogs/FilePickerForm.js index 51d59a9..6414818 100644 --- a/ui/tools/FilePickerForm.js +++ b/ui/dialogs/FilePickerForm.js @@ -1,15 +1,11 @@ -const fs = require('fs') -const util = require('util') -const path = require('path') +import {readdir, stat} from 'node:fs/promises' +import path from 'node:path' -const readdir = util.promisify(fs.readdir) -const stat = util.promisify(fs.stat) -const naturalSort = require('node-natural-sort') +import {compare as naturalCompare} from 'natural-orderby' -const Button = require('../form/Button') -const ListScrollForm = require('../form/ListScrollForm') +import {Button, ListScrollForm} from 'tui-lib/ui/controls' -module.exports = class FilePickerForm extends ListScrollForm { +export default class FilePickerForm extends ListScrollForm { fillItems(dirPath) { this.inputs = [] this.children = [] @@ -33,14 +29,10 @@ module.exports = class FilePickerForm extends ListScrollForm { }) })) - const sort = naturalSort({ - properties: { - caseSensitive: false - } - }) + const compare = naturalCompare() processedItems.sort((a, b) => { if (a.isDirectory === b.isDirectory) { - return sort(a.label, b.label) + return compare(a.label, b.label) } else { if (a.isDirectory) { return -1 @@ -85,4 +77,3 @@ module.exports = class FilePickerForm extends ListScrollForm { }) } } - diff --git a/ui/tools/OpenFileDialog.js b/ui/dialogs/OpenFileDialog.js index 43f2638..970e291 100644 --- a/ui/tools/OpenFileDialog.js +++ b/ui/dialogs/OpenFileDialog.js @@ -1,13 +1,12 @@ -const path = require('path') +import path from 'node:path' -const Button = require('../form/Button') -const Dialog = require('../Dialog') -const FilePickerForm = require('./FilePickerForm') -const Form = require('../form/Form') -const Label = require('../Label') -const TextInput = require('../form/TextInput') +import {Button, Form, TextInput} from 'tui-lib/ui/controls' +import {Label} from 'tui-lib/ui/presentation' -module.exports = class OpenFileDialog extends Dialog { +import Dialog from './Dialog.js' +import FilePickerForm from './FilePickerForm.js' + +export default class OpenFileDialog extends Dialog { constructor() { super() @@ -42,7 +41,7 @@ module.exports = class OpenFileDialog extends Dialog { { const cb = append => p => { - this.filePathInput.setValue((path.relative(__dirname, p) || '.') + append) + this.filePathInput.setValue((path.relative(process.cwd(), p) || '.') + append) } this.filePickerForm.on('selected', cb('')) @@ -54,7 +53,7 @@ module.exports = class OpenFileDialog extends Dialog { }) const dir = (this.lastFilePath - ? path.relative(__dirname, path.dirname(this.lastFilePath)) + '/' + ? path.relative(process.cwd(), path.dirname(this.lastFilePath)) + '/' : './') this.filePathInput.setValue(dir) @@ -107,4 +106,3 @@ module.exports = class OpenFileDialog extends Dialog { }) } } - diff --git a/ui/dialogs/index.js b/ui/dialogs/index.js new file mode 100644 index 0000000..5cb9f04 --- /dev/null +++ b/ui/dialogs/index.js @@ -0,0 +1,16 @@ +// +// Import mapping: +// +// controls, presentation, primitives -> +// CancelDialog +// ConfirmDialog +// +// Dialog -> OpenFileDialog +// FilePickerForm -> OpenFileDialog +// + +export {default as CancelDialog} from './CancelDialog.js' +export {default as ConfirmDialog} from './ConfirmDialog.js' +export {default as Dialog} from './Dialog.js' +export {default as FilePickerForm} from './FilePickerForm.js' +export {default as OpenFileDialog} from './OpenFileDialog.js' diff --git a/ui/index.js b/ui/index.js new file mode 100644 index 0000000..df6cae8 --- /dev/null +++ b/ui/index.js @@ -0,0 +1,4 @@ +export * as controls from './controls/index.js' +export * as dialogs from './dialogs/index.js' +export * as presentation from './presentation/index.js' +export * as primitives from './primitives/index.js' diff --git a/ui/HorizontalBox.js b/ui/presentation/HorizontalBox.js index f92bf10..d396ec3 100644 --- a/ui/HorizontalBox.js +++ b/ui/presentation/HorizontalBox.js @@ -1,6 +1,6 @@ -const DisplayElement = require('./DisplayElement') +import {DisplayElement} from 'tui-lib/ui/primitives' -module.exports = class HorizontalBox extends DisplayElement { +export default class HorizontalBox extends DisplayElement { // A box that will automatically lay out its children in a horizontal row. fixLayout() { diff --git a/ui/Label.js b/ui/presentation/Label.js index f2cd405..81223df 100644 --- a/ui/Label.js +++ b/ui/presentation/Label.js @@ -1,8 +1,8 @@ -const ansi = require('../util/ansi') +import {DisplayElement} from 'tui-lib/ui/primitives' -const DisplayElement = require('./DisplayElement') +import * as ansi from 'tui-lib/util/ansi' -module.exports = class Label extends DisplayElement { +export default class Label extends DisplayElement { // A simple text display. Automatically adjusts size to fit text. constructor(text = '') { diff --git a/ui/Pane.js b/ui/presentation/Pane.js index b33a1b7..4769cf9 100644 --- a/ui/Pane.js +++ b/ui/presentation/Pane.js @@ -1,11 +1,11 @@ -const ansi = require('../util/ansi') -const unic = require('../util/unichars') +import {DisplayElement} from 'tui-lib/ui/primitives' -const DisplayElement = require('./DisplayElement') +import * as ansi from 'tui-lib/util/ansi' +import unic from 'tui-lib/util/unichars' -const Label = require('./Label') +import Label from './Label.js' -module.exports = class Pane extends DisplayElement { +export default class Pane extends DisplayElement { // A simple rectangular framed pane. constructor() { diff --git a/ui/Sprite.js b/ui/presentation/Sprite.js index 701f1b8..49ee450 100644 --- a/ui/Sprite.js +++ b/ui/presentation/Sprite.js @@ -1,8 +1,8 @@ -const ansi = require('../util/ansi') +import {DisplayElement} from 'tui-lib/ui/primitives' -const DisplayElement = require('./DisplayElement') +import * as ansi from 'tui-lib/util/ansi' -module.exports = class Sprite extends DisplayElement { +export default class Sprite extends DisplayElement { // "A sprite is a two-dimensional bitmap that is integrated into a larger // scene." - Wikipedia // diff --git a/ui/WrapLabel.js b/ui/presentation/WrapLabel.js index babf462..0ecc777 100644 --- a/ui/WrapLabel.js +++ b/ui/presentation/WrapLabel.js @@ -1,9 +1,10 @@ -const ansi = require('../util/ansi') -const wrap = require('word-wrap') +import wrap from 'word-wrap' -const Label = require('./Label') +import * as ansi from 'tui-lib/util/ansi' -module.exports = class WrapLabel extends Label { +import Label from './Label.js' + +export default class WrapLabel extends Label { // A word-wrapping text display. Given a width, wraps text to fit. constructor(...args) { diff --git a/ui/presentation/index.js b/ui/presentation/index.js new file mode 100644 index 0000000..9605d25 --- /dev/null +++ b/ui/presentation/index.js @@ -0,0 +1,15 @@ +// +// Import mapping: +// +// primitives -> +// HorizontalBox +// Sprite +// +// Label -> Pane, WrapLabel +// + +export {default as HorizontalBox} from './HorizontalBox.js' +export {default as Label} from './Label.js' +export {default as Pane} from './Pane.js' +export {default as Sprite} from './Sprite.js' +export {default as WrapLabel} from './WrapLabel.js' diff --git a/ui/DisplayElement.js b/ui/primitives/DisplayElement.js index 8720142..d2a0956 100644 --- a/ui/DisplayElement.js +++ b/ui/primitives/DisplayElement.js @@ -1,7 +1,6 @@ -const Element = require('./Element') -const exception = require('../util/exception') +import Element from './Element.js' -module.exports = class DisplayElement extends Element { +export default class DisplayElement extends Element { // A general class that handles dealing with screen coordinates, the tree // of elements, and other common stuff. // @@ -11,6 +10,10 @@ module.exports = class DisplayElement extends Element { // It's a subclass of EventEmitter, so you can make your own events within // the logic of your subclass. + static drawValues = Symbol('drawValues') + static lastDrawValues = Symbol('lastDrawValues') + static scheduledDraw = Symbol('scheduledDraw') + constructor() { super() @@ -300,7 +303,3 @@ module.exports = class DisplayElement extends Element { get absTop() { return this.absY } get absBottom() { return this.absY + this.h - 1 } } - -module.exports.drawValues = Symbol('drawValues') -module.exports.lastDrawValues = Symbol('lastDrawValues') -module.exports.scheduledDraw = Symbol('scheduledDraw') diff --git a/ui/Element.js b/ui/primitives/Element.js index c5beb59..fea8c03 100644 --- a/ui/Element.js +++ b/ui/primitives/Element.js @@ -1,6 +1,6 @@ -const EventEmitter = require('events') +import EventEmitter from 'node:events' -module.exports = class Element extends EventEmitter { +export default class Element extends EventEmitter { // The basic class containing methods for working with an element hierarchy. // Generally speaking, you usually want to extend DisplayElement instead of // this class. diff --git a/ui/form/FocusElement.js b/ui/primitives/FocusElement.js index 23c2e02..2c23b1e 100644 --- a/ui/form/FocusElement.js +++ b/ui/primitives/FocusElement.js @@ -1,6 +1,6 @@ -const DisplayElement = require('../DisplayElement') +import DisplayElement from './DisplayElement.js' -module.exports = class FocusElement extends DisplayElement { +export default class FocusElement extends DisplayElement { // A basic element that can receive cursor focus. constructor() { diff --git a/ui/Root.js b/ui/primitives/Root.js index 2b13203..a779637 100644 --- a/ui/Root.js +++ b/ui/primitives/Root.js @@ -1,19 +1,17 @@ -const ansi = require('../util/ansi') -const telc = require('../util/telchars') +import * as ansi from 'tui-lib/util/ansi' +import telc from 'tui-lib/util/telchars' -const DisplayElement = require('./DisplayElement') +import DisplayElement from './DisplayElement.js' -const Form = require('./form/Form') - -module.exports = class Root extends DisplayElement { +export default class Root extends DisplayElement { // An element to be used as the root of a UI. Handles lots of UI and // socket stuff. - constructor(interfacer, writable = null) { + constructor(interfaceArg, writable = null) { super() - this.interfacer = interfacer - this.writable = writable || interfacer + this.interface = interfaceArg + this.writable = writable || interfaceArg this.selectedElement = null @@ -21,7 +19,7 @@ module.exports = class Root extends DisplayElement { this.oldSelectionStates = [] - interfacer.on('inputData', buf => this.handleData(buf)) + this.interface.on('inputData', buf => this.handleData(buf)) this.renderCount = 0 } @@ -174,11 +172,17 @@ module.exports = class Root extends DisplayElement { // If the element is part of a form, just be lazy and pass control to that // form...unless the form itself asked us to select the element! + // // TODO: This is so that if an element is selected, its parent form will // automatically see that and correctly update its curIndex... but what if // the element is an input of a form which is NOT its parent? + // + // XXX: We currently use a HUGE HACK instead of `instanceof` to avoid + // breaking the rule of import direction (controls -> primitives, never + // the other way around). This is bad for obvious reasons, but I haven't + // yet looked into what the correct approach would be. const parent = el.parent - if (!fromForm && parent instanceof Form && parent.inputs.includes(el)) { + if (!fromForm && parent.constructor.name === 'Form' && parent.inputs.includes(el)) { parent.selectInput(el) return } diff --git a/ui/primitives/index.js b/ui/primitives/index.js new file mode 100644 index 0000000..4e36452 --- /dev/null +++ b/ui/primitives/index.js @@ -0,0 +1,11 @@ +// +// Import mapping: +// +// Element -> +// DisplayElement -> FocusElement, Root +// + +export {default as DisplayElement} from './DisplayElement.js' +export {default as Element} from './Element.js' +export {default as FocusElement} from './FocusElement.js' +export {default as Root} from './Root.js' |