@hypericon/mico 0.2.0 → 0.2.2

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.
package/README.md CHANGED
@@ -6,3 +6,9 @@
6
6
  UI components and utilities built with Mithril.
7
7
 
8
8
  <a href="https://www.npmjs.com/package/@hypericon/mico">![NPM badge](https://img.shields.io/npm/v/@hypericon/mico)</a>
9
+
10
+ ## Installation
11
+
12
+ ```sh
13
+ $ npm i @hypericon/mico
14
+ ```
@@ -1,2 +1,4 @@
1
1
  export * from "./icon";
2
2
  export * from "./markdown";
3
+ export * from "./menu";
4
+ export * from "./table";
@@ -21,12 +21,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
21
21
  // export * from "./form";
22
22
  __exportStar(require("./icon"), exports);
23
23
  __exportStar(require("./markdown"), exports);
24
- // export * from "./menu";
24
+ __exportStar(require("./menu"), exports);
25
25
  // export * from "./modal";
26
26
  // export * from "./pagination";
27
27
  // export * from "./popover";
28
28
  // export * from "./reorderable-list";
29
- // export * from "./table";
29
+ __exportStar(require("./table"), exports);
30
30
  // export * from "./toast";
31
31
  // export * from "./tooltip";
32
32
  // export * from "./tree";
@@ -22,6 +22,11 @@ export declare const Markdown: m.Component<{
22
22
  unsanitised?: boolean;
23
23
  /** Highlight syntax */
24
24
  highlight?: boolean;
25
+ /**
26
+ * Wrap all the given "markdown" in triple-backticks with the given language string and enable highlighting
27
+ * @example "typescript"
28
+ */
29
+ highlightAllAs?: string;
25
30
  /** CSS classes to apply to the container div */
26
31
  class?: string;
27
32
  /** CSS styles to apply to the container div */
@@ -27,7 +27,7 @@ exports.MARKDOWN_DEFAULT_OPTIONS = {
27
27
  exports.Markdown = {
28
28
  oncreate({ attrs }) {
29
29
  var _a;
30
- if (attrs.highlight === true) {
30
+ if (attrs.highlight === true || Boolean(attrs.highlightAllAs)) {
31
31
  // console.log("highlighting...");
32
32
  (_a = window.hljs) === null || _a === void 0 ? void 0 : _a.highlightAll();
33
33
  // hljs.highlightAll();
@@ -41,7 +41,10 @@ exports.Markdown = {
41
41
  // },
42
42
  view({ attrs, children }) {
43
43
  var _a, _b, _c, _d, _e, _f;
44
- const markdown = (_c = (_b = (_a = attrs.markdown) !== null && _a !== void 0 ? _a : (typeof children === "string" ? children : undefined)) !== null && _b !== void 0 ? _b : (children instanceof Array && children.length > 0 && typeof children[0] === "string" ? children[0] : undefined)) !== null && _c !== void 0 ? _c : "";
44
+ let markdown = (_c = (_b = (_a = attrs.markdown) !== null && _a !== void 0 ? _a : (typeof children === "string" ? children : undefined)) !== null && _b !== void 0 ? _b : (children instanceof Array && children.length > 0 && typeof children[0] === "string" ? children[0] : undefined)) !== null && _c !== void 0 ? _c : "";
45
+ if (attrs.highlightAllAs) {
46
+ markdown = "```" + attrs.highlightAllAs + "\n" + markdown + "\n" + "```";
47
+ }
45
48
  const parsed = marked_1.marked.parse(markdown, (_d = attrs.markedOptions) !== null && _d !== void 0 ? _d : exports.MARKDOWN_DEFAULT_OPTIONS);
46
49
  const sanitised = attrs.unsanitised === true ? parsed : dompurify_1.default.sanitize(parsed);
47
50
  const result = sanitised;
@@ -0,0 +1,7 @@
1
+ import m from "mithril";
2
+ export declare const Menu: m.Component<{
3
+ x: number | undefined;
4
+ y: number | undefined;
5
+ }, {
6
+ el?: HTMLDivElement;
7
+ }>;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Menu = void 0;
7
+ const mithril_1 = __importDefault(require("mithril"));
8
+ const menu_constants_1 = require("./menu-constants");
9
+ const menu_settings_1 = require("./menu-settings");
10
+ exports.Menu = {
11
+ oninit() { },
12
+ oncreate({ dom }) {
13
+ if (dom) {
14
+ this.el = dom;
15
+ this.el.focus();
16
+ }
17
+ },
18
+ onupdate({ dom }) {
19
+ // if (dom) this.el = dom as HTMLDivElement;
20
+ },
21
+ view({ attrs, children, }) {
22
+ var _a, _b;
23
+ const maxWidthPx = Math.min(window.innerWidth, menu_constants_1.MENU_CONSTANTS.MAX_WIDTH_PX);
24
+ const maxHeightPx = window.innerHeight / 2;
25
+ const xPx = (_a = attrs.x) !== null && _a !== void 0 ? _a : 0;
26
+ const yPx = (_b = attrs.y) !== null && _b !== void 0 ? _b : 0;
27
+ const flipH = ((xPx + menu_constants_1.MENU_CONSTANTS.MIN_WIDTH_PX) > window.innerWidth);
28
+ const flipV = menu_settings_1.MENU_SETTINGS.ANCHOR === "page"
29
+ ? ((yPx + maxHeightPx - window.scrollY) > window.innerHeight)
30
+ : ((yPx + maxHeightPx) > window.innerHeight);
31
+ // console.log({
32
+ // "yPx": yPx,
33
+ // "maxHeightPx": maxHeightPx,
34
+ // "window.scrollY": window.scrollY,
35
+ // "window.innerHeight": window.innerHeight,
36
+ // "flipV": flipV,
37
+ // });
38
+ // TODO: don't let the menu width actually touch the screen width; it will fall off the left hand side
39
+ const posH = flipH ? `right: ${window.innerWidth - xPx}px;` : `left: ${xPx}px;`;
40
+ const posV = flipV ? `bottom: ${window.innerHeight - yPx}px;` : `top: ${yPx}px;`;
41
+ return (0, mithril_1.default)("", {
42
+ key: Date.now(),
43
+ class: menu_settings_1.MENU_SETTINGS.MENU_CLASS,
44
+ style: `position: absolute; overflow-y: auto; overflow-x: hidden; ${posH} ${posV} z-index: 100; min-width: ${menu_constants_1.MENU_CONSTANTS.MIN_WIDTH_PX}px; max-width: ${maxWidthPx}px; max-height: ${maxHeightPx}px;`,
45
+ tabIndex: -1,
46
+ onkeydown: (ev) => {
47
+ var _a, _b, _c, _d, _e, _f;
48
+ const focussableElems = Array.from((_b = (_a = this.el) === null || _a === void 0 ? void 0 : _a.querySelectorAll("button, input, select, textarea")) !== null && _b !== void 0 ? _b : [])
49
+ .filter(el => !Boolean(el.disabled));
50
+ let focusIndex = -1;
51
+ if (focussableElems) {
52
+ for (let i = 0; i < focussableElems.length; i++) {
53
+ const element = focussableElems[i];
54
+ if (document.activeElement === element) {
55
+ focusIndex = i;
56
+ break;
57
+ }
58
+ }
59
+ }
60
+ if (ev.key === "ArrowDown") {
61
+ // console.log("move down, focussable list:", focussableElems, "this.el", this.el);
62
+ focusIndex += 1;
63
+ if (focusIndex >= focussableElems.length)
64
+ focusIndex = 0;
65
+ (_d = (_c = focussableElems[focusIndex]).focus) === null || _d === void 0 ? void 0 : _d.call(_c);
66
+ }
67
+ if (ev.key === "ArrowUp") {
68
+ // console.log("move up, focussable list:", focussableElems, "this.el", this.el);
69
+ focusIndex -= 1;
70
+ if (focusIndex < 0)
71
+ focusIndex = focussableElems.length - 1;
72
+ (_f = (_e = focussableElems[focusIndex]).focus) === null || _f === void 0 ? void 0 : _f.call(_e);
73
+ }
74
+ },
75
+ }, [
76
+ children,
77
+ ]);
78
+ }
79
+ };
@@ -0,0 +1,14 @@
1
+ import m from "mithril";
2
+ import { IconAttrs } from "../icon";
3
+ export declare const MenuButton: m.Component<{
4
+ icon?: m.Vnode<any, any> | IconAttrs;
5
+ label?: string;
6
+ hint?: string;
7
+ disabled?: boolean;
8
+ onclick?: (ev: MouseEvent) => any;
9
+ onhover?: (ev: MouseEvent) => any;
10
+ onprev?: (ev: KeyboardEvent) => any;
11
+ onnext?: (ev: KeyboardEvent) => any;
12
+ class?: string;
13
+ style?: string;
14
+ }>;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MenuButton = void 0;
7
+ const mithril_1 = __importDefault(require("mithril"));
8
+ const icon_1 = require("../icon");
9
+ const menu_settings_1 = require("./menu-settings");
10
+ exports.MenuButton = {
11
+ view({ attrs }) {
12
+ var _a, _b;
13
+ return (0, mithril_1.default)("button", {
14
+ class: `${(_a = attrs.class) !== null && _a !== void 0 ? _a : ""} ${menu_settings_1.MENU_SETTINGS.MENU_BUTTON_CLASS}`,
15
+ style: `${(_b = attrs.style) !== null && _b !== void 0 ? _b : ""} width: 100%; height: 1.5rem; padding-right: 0.5rem; display: flex; align-items: center;`,
16
+ disabled: attrs.disabled,
17
+ onclick: (ev) => {
18
+ var _a;
19
+ (_a = attrs.onclick) === null || _a === void 0 ? void 0 : _a.call(attrs, ev);
20
+ mithril_1.default.redraw();
21
+ },
22
+ }, [
23
+ (0, mithril_1.default)("", {
24
+ // class: attrs.disabled ? "text-disabled" : "text-icon",
25
+ class: menu_settings_1.MENU_SETTINGS.MENU_BUTTON_ICON_CLASS,
26
+ style: "width: 2rem; flex: none; display: flex; align-items: center; justify-content: space-around;",
27
+ }, [
28
+ attrs.icon ? [
29
+ ("fas" in attrs.icon || "far" in attrs.icon || "fab" in attrs.icon)
30
+ ? (0, mithril_1.default)(icon_1.Icon, Object.assign({}, attrs.icon))
31
+ : attrs.icon,
32
+ ] : [],
33
+ ]),
34
+ (0, mithril_1.default)("span", {
35
+ class: menu_settings_1.MENU_SETTINGS.MENU_BUTTON_LABEL_CLASS,
36
+ style: "overflow: hidden; text-overflow: ellipsis; white-space: nowrap;",
37
+ }, attrs.label),
38
+ (0, mithril_1.default)("", { style: "flex: 1 1 0%;" }),
39
+ attrs.hint
40
+ ? (0, mithril_1.default)("span", {
41
+ class: menu_settings_1.MENU_SETTINGS.MENU_BUTTON_HINT_CLASS,
42
+ style: "overflow: hidden; text-overflow: ellipsis; white-space: nowrap;",
43
+ }, attrs.hint)
44
+ : [],
45
+ ]);
46
+ }
47
+ };
@@ -0,0 +1,2 @@
1
+ import m from "mithril";
2
+ export declare const MenuSeparator: m.Component<{}>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MenuSeparator = void 0;
7
+ const mithril_1 = __importDefault(require("mithril"));
8
+ const menu_settings_1 = require("./menu-settings");
9
+ exports.MenuSeparator = {
10
+ view() {
11
+ // return m(".my-2.ml-8.mr-2.border-b.border-slate-300");
12
+ return (0, mithril_1.default)("", {
13
+ class: menu_settings_1.MENU_SETTINGS.MENU_SEPARATOR_CLASS,
14
+ style: "margin: 0.25rem 0; border-bottom: 1px;",
15
+ });
16
+ }
17
+ };
@@ -0,0 +1,6 @@
1
+ export * from "./Menu";
2
+ export * from "./MenuButton";
3
+ export * from "./MenuSeparator";
4
+ export * from "./menu-constants";
5
+ export * from "./menu-service";
6
+ export * from "./menu-settings";
@@ -1 +1,22 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Menu"), exports);
18
+ __exportStar(require("./MenuButton"), exports);
19
+ __exportStar(require("./MenuSeparator"), exports);
20
+ __exportStar(require("./menu-constants"), exports);
21
+ __exportStar(require("./menu-service"), exports);
22
+ __exportStar(require("./menu-settings"), exports);
@@ -0,0 +1,4 @@
1
+ export declare const MENU_CONSTANTS: {
2
+ readonly MIN_WIDTH_PX: 200;
3
+ readonly MAX_WIDTH_PX: 500;
4
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MENU_CONSTANTS = void 0;
4
+ exports.MENU_CONSTANTS = {
5
+ MIN_WIDTH_PX: 200,
6
+ MAX_WIDTH_PX: 500,
7
+ };
@@ -0,0 +1,21 @@
1
+ import m from "mithril";
2
+ export declare class MenuService {
3
+ private containerEl;
4
+ private _menuVnode;
5
+ menuVnode$: import("rxjs").Observable<m.Vnode<any, any> | undefined>;
6
+ get menuVnode(): m.Vnode<any, any> | undefined;
7
+ get isOpen(): boolean;
8
+ constructor();
9
+ /**
10
+ * Show a new "right-click" menu at the position of the given mouse event,
11
+ * containing the given menu contents.
12
+ *
13
+ * This function handles stopping the mouse event propagation and aiting for any previous menus
14
+ * to be cleared.
15
+ * @param ev
16
+ * @param menuContents
17
+ */
18
+ show(ev: MouseEvent | undefined, menuContents: m.ChildArrayOrPrimitive): Promise<void>;
19
+ hide(): void;
20
+ }
21
+ export declare const menuService: MenuService;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.menuService = exports.MenuService = void 0;
16
+ const mithril_1 = __importDefault(require("mithril"));
17
+ const rxjs_1 = require("rxjs");
18
+ const Menu_1 = require("./Menu");
19
+ const menu_settings_1 = require("./menu-settings");
20
+ class MenuService {
21
+ get menuVnode() { return this._menuVnode.value; }
22
+ get isOpen() {
23
+ return Boolean(this.menuVnode);
24
+ }
25
+ constructor() {
26
+ this._menuVnode = new rxjs_1.BehaviorSubject(undefined);
27
+ this.menuVnode$ = this._menuVnode.asObservable();
28
+ this.containerEl = document.createElement("div");
29
+ this.containerEl.classList.add("menu-container");
30
+ document.body.append(this.containerEl);
31
+ document.addEventListener("click", () => {
32
+ if (this.isOpen) {
33
+ this.hide();
34
+ }
35
+ });
36
+ document.addEventListener("keydown", (ev) => {
37
+ if (this.isOpen && (ev.key === "Escape")) {
38
+ this.hide();
39
+ }
40
+ });
41
+ }
42
+ /**
43
+ * Show a new "right-click" menu at the position of the given mouse event,
44
+ * containing the given menu contents.
45
+ *
46
+ * This function handles stopping the mouse event propagation and aiting for any previous menus
47
+ * to be cleared.
48
+ * @param ev
49
+ * @param menuContents
50
+ */
51
+ show(ev, menuContents) {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ ev === null || ev === void 0 ? void 0 : ev.stopPropagation();
54
+ if (this.isOpen) {
55
+ this.hide();
56
+ }
57
+ yield new Promise((resolve, reject) => {
58
+ setTimeout(() => resolve(), 0);
59
+ });
60
+ const menuVnode = (0, mithril_1.default)(Menu_1.Menu, {
61
+ x: ev === null || ev === void 0 ? void 0 : ev.clientX,
62
+ y: menu_settings_1.MENU_SETTINGS.ANCHOR === "page" ? ev === null || ev === void 0 ? void 0 : ev.pageY : ev === null || ev === void 0 ? void 0 : ev.clientY,
63
+ }, [
64
+ menuContents,
65
+ ]);
66
+ this._menuVnode.next(menuVnode);
67
+ mithril_1.default.render(this.containerEl, menuVnode);
68
+ // console.log("Added menu");
69
+ });
70
+ }
71
+ hide() {
72
+ this._menuVnode.next(undefined);
73
+ mithril_1.default.render(this.containerEl, []);
74
+ // console.log("Closed menu");
75
+ }
76
+ }
77
+ exports.MenuService = MenuService;
78
+ exports.menuService = new MenuService();
@@ -0,0 +1,9 @@
1
+ export declare const MENU_SETTINGS: {
2
+ ANCHOR: "page" | "screen";
3
+ MENU_CLASS: string;
4
+ MENU_BUTTON_CLASS: string;
5
+ MENU_BUTTON_LABEL_CLASS: string;
6
+ MENU_BUTTON_ICON_CLASS: string;
7
+ MENU_BUTTON_HINT_CLASS: string;
8
+ MENU_SEPARATOR_CLASS: string;
9
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MENU_SETTINGS = void 0;
4
+ exports.MENU_SETTINGS = {
5
+ ANCHOR: "page",
6
+ MENU_CLASS: "",
7
+ MENU_BUTTON_CLASS: "",
8
+ MENU_BUTTON_LABEL_CLASS: "",
9
+ MENU_BUTTON_ICON_CLASS: "",
10
+ MENU_BUTTON_HINT_CLASS: "",
11
+ MENU_SEPARATOR_CLASS: "",
12
+ };
@@ -0,0 +1,54 @@
1
+ import m from "mithril";
2
+ export type TableCellDisplayFn<T> = (item: T, index: number) => string | number | boolean | m.Vnode<any, any> | null | undefined;
3
+ export type TableColumnDefinition<T> = {
4
+ header: string | m.Vnode<any, any>;
5
+ cell: TableCellDisplayFn<T>;
6
+ };
7
+ export interface TableAttrs<T> {
8
+ /** The list of items to display as rows */
9
+ data: T[];
10
+ /** The definitions of the table columns */
11
+ columns: TableColumnDefinition<T>[];
12
+ /** Set the table to automatically size columns to fit (default), or use fixed column widths */
13
+ layout?: "auto" | "fixed";
14
+ /** Override the default message displayed when there are no data items */
15
+ emptyMessage?: string;
16
+ /** Any CSS classes to apply to the table */
17
+ class?: string;
18
+ /** Any CSS styles to apply to the table */
19
+ style?: string;
20
+ }
21
+ export interface TableState<T> {
22
+ }
23
+ /** Helper function to make it easier to define table columns */
24
+ export type TableColumnDefinitionFn<T> = (
25
+ /** The label or other element to display in the header */
26
+ header: string | m.Vnode<any, any>,
27
+ /** Function defining how to display a cell in the column using the given row item */
28
+ cell: TableCellDisplayFn<T>) => TableColumnDefinition<T>;
29
+ /**
30
+ * Build a typed Table component which includes type checking for column definitions
31
+ * @example
32
+ * ```ts
33
+ * const PersonTable = typedTable<Person>();
34
+ * m(PersonTable, {
35
+ * data: people, // `data` is type checked
36
+ * columns: [
37
+ * PersonTable.col("Name", p => p.name), // `p` is type checked
38
+ * PersonTable.col("Age", p => findAge(p.dob)), // `p` is type checked
39
+ * ],
40
+ * }),
41
+ * ```
42
+ * @returns
43
+ */
44
+ export declare function typedTable<T>(): {
45
+ col: TableColumnDefinitionFn<T>;
46
+ oninit?(this: m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>, vnode: m.Vnode<TableAttrs<T>, m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>>): any;
47
+ oncreate?(this: m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>, vnode: m.VnodeDOM<TableAttrs<T>, m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>>): any;
48
+ onbeforeremove?(this: m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>, vnode: m.VnodeDOM<TableAttrs<T>, m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>>): void | Promise<any>;
49
+ onremove?(this: m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>, vnode: m.VnodeDOM<TableAttrs<T>, m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>>): any;
50
+ onbeforeupdate?(this: m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>, vnode: m.Vnode<TableAttrs<T>, m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>>, old: m.VnodeDOM<TableAttrs<T>, m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>>): boolean | void;
51
+ onupdate?(this: m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>, vnode: m.VnodeDOM<TableAttrs<T>, m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>>): any;
52
+ view(this: m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>, vnode: m.Vnode<TableAttrs<T>, m._NoLifecycle<m.Component<TableAttrs<T>, TableState<T>> & TableState<T>>>): void | m.Children;
53
+ };
54
+ export declare const Table: m.Component<TableAttrs<any>, TableState<any>>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Table = exports.typedTable = void 0;
7
+ const mithril_1 = __importDefault(require("mithril"));
8
+ /**
9
+ * Build a typed Table component which includes type checking for column definitions
10
+ * @example
11
+ * ```ts
12
+ * const PersonTable = typedTable<Person>();
13
+ * m(PersonTable, {
14
+ * data: people, // `data` is type checked
15
+ * columns: [
16
+ * PersonTable.col("Name", p => p.name), // `p` is type checked
17
+ * PersonTable.col("Age", p => findAge(p.dob)), // `p` is type checked
18
+ * ],
19
+ * }),
20
+ * ```
21
+ * @returns
22
+ */
23
+ function typedTable() {
24
+ const typedTable = exports.Table;
25
+ const col = (header, cell) => {
26
+ return { header, cell };
27
+ };
28
+ return Object.assign(Object.assign({}, typedTable), { col });
29
+ }
30
+ exports.typedTable = typedTable;
31
+ exports.Table = {
32
+ view({ attrs }) {
33
+ var _a, _b, _c, _d;
34
+ return (0, mithril_1.default)("table", {
35
+ class: attrs.class,
36
+ style: `${(_a = attrs.style) !== null && _a !== void 0 ? _a : ""} table-layout: ${((_b = attrs.layout) !== null && _b !== void 0 ? _b : "auto")};`,
37
+ }, [
38
+ (0, mithril_1.default)("thead", [
39
+ (0, mithril_1.default)("tr", [
40
+ attrs.columns.map(col => {
41
+ return (0, mithril_1.default)("th", [
42
+ col.header,
43
+ ]);
44
+ }),
45
+ ]),
46
+ ]),
47
+ (0, mithril_1.default)("tbody", [
48
+ attrs.data.map(item => {
49
+ return (0, mithril_1.default)("tr", [
50
+ attrs.columns.map((col, index) => {
51
+ var _a;
52
+ return (0, mithril_1.default)("td", [
53
+ (_a = col.cell) === null || _a === void 0 ? void 0 : _a.call(col, item, index),
54
+ ]);
55
+ }),
56
+ ]);
57
+ }),
58
+ ((_c = attrs.data) === null || _c === void 0 ? void 0 : _c.length) === 0 ? (0, mithril_1.default)("tr", [
59
+ (0, mithril_1.default)("td.text-center.text-medium", {
60
+ colspan: attrs.columns.length,
61
+ }, [
62
+ (_d = attrs.emptyMessage) !== null && _d !== void 0 ? _d : "No items",
63
+ ]),
64
+ ]) : [],
65
+ ]),
66
+ ]);
67
+ }
68
+ };
@@ -0,0 +1 @@
1
+ export * from "./Table";
@@ -1 +1,17 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Table"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypericon/mico",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "UI components and utilities with Mithril",
5
5
  "author": "Ed Johnson, Hypericon Ltd",
6
6
  "license": "MIT",
@@ -20,7 +20,8 @@
20
20
  "dompurify": "^3.0.3",
21
21
  "highlight.js": "^11.8.0",
22
22
  "marked": "^4.3.0",
23
- "mithril": "^2.2.2"
23
+ "mithril": "^2.2.2",
24
+ "rxjs": "^7.8.1"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@types/dompurify": "^3.0.2",