@malloydata/render 0.0.202-dev241013162457 → 0.0.202-dev241018164632
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/.storybook/main.ts +15 -3
- package/.storybook/malloy-stories-indexer.ts +172 -0
- package/.storybook/preview.ts +10 -3
- package/dist/module/index.mjs +13232 -13206
- package/dist/module/index.umd.js +266 -266
- package/dist/register/register.mjs +13507 -13481
- package/dist/register/register.umd.js +247 -247
- package/dist/stories/util.d.ts +9 -0
- package/dist/webcomponent/malloy-render.mjs +13507 -13481
- package/dist/webcomponent/malloy-render.umd.js +247 -247
- package/package.json +14 -11
- package/dist/stories/areas.stories.d.ts +0 -59
- package/dist/stories/bars.stories.d.ts +0 -59
- package/dist/stories/basic.stories.d.ts +0 -43
- package/dist/stories/dashboard.stories.d.ts +0 -23
- package/dist/stories/image-legacy.stories.d.ts +0 -31
- package/dist/stories/image.stories.d.ts +0 -29
- package/dist/stories/legacy-charts.stories.d.ts +0 -29
- package/dist/stories/lines.stories.d.ts +0 -59
- package/dist/stories/link-legacy.stories.d.ts +0 -31
- package/dist/stories/link.stories.d.ts +0 -29
- package/dist/stories/list.stories.d.ts +0 -41
- package/dist/stories/render-malloy-legacy.d.ts +0 -6
- package/dist/stories/tables.stories.d.ts +0 -72
package/.storybook/main.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {join, dirname} from 'path';
|
|
2
2
|
import {mergeConfig, InlineConfig} from 'vite';
|
|
3
3
|
import {StorybookConfig} from '@storybook/html-vite';
|
|
4
|
+
import {
|
|
5
|
+
malloyStoriesIndexer,
|
|
6
|
+
viteMalloyStoriesPlugin,
|
|
7
|
+
} from './malloy-stories-indexer';
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* This function is used to resolve the absolute path of a package.
|
|
@@ -13,21 +17,28 @@ function getAbsolutePath(value) {
|
|
|
13
17
|
const config: StorybookConfig = {
|
|
14
18
|
'stories': [
|
|
15
19
|
'../src/stories/*.mdx',
|
|
20
|
+
'../src/**/*.stories.malloy',
|
|
16
21
|
'../src/**/*.stories.@(js|jsx|mjs|ts|tsx)',
|
|
17
22
|
],
|
|
23
|
+
experimental_indexers: async existingIndexers => [
|
|
24
|
+
...(existingIndexers ?? []),
|
|
25
|
+
malloyStoriesIndexer,
|
|
26
|
+
],
|
|
18
27
|
staticDirs: ['../src/stories/static'],
|
|
19
28
|
'addons': [
|
|
20
29
|
getAbsolutePath('@storybook/addon-links'),
|
|
21
30
|
getAbsolutePath('@storybook/addon-essentials'),
|
|
22
31
|
getAbsolutePath('@storybook/addon-interactions'),
|
|
23
32
|
],
|
|
33
|
+
core: {
|
|
34
|
+
builder: '@storybook/builder-vite',
|
|
35
|
+
disableTelemetry: true,
|
|
36
|
+
},
|
|
24
37
|
'framework': {
|
|
25
38
|
'name': '@storybook/html-vite',
|
|
26
39
|
'options': {},
|
|
27
40
|
},
|
|
28
|
-
'docs': {
|
|
29
|
-
'autodocs': 'tag',
|
|
30
|
-
},
|
|
41
|
+
'docs': {},
|
|
31
42
|
async viteFinal(config, {configType}) {
|
|
32
43
|
if (configType === 'DEVELOPMENT') {
|
|
33
44
|
// Your development configuration goes here
|
|
@@ -54,6 +65,7 @@ const config: StorybookConfig = {
|
|
|
54
65
|
'process.env': {},
|
|
55
66
|
},
|
|
56
67
|
assetsInclude: ['/sb-preview/runtime.js'],
|
|
68
|
+
plugins: [viteMalloyStoriesPlugin()],
|
|
57
69
|
};
|
|
58
70
|
const finalConfig = mergeConfig(config, configOverride);
|
|
59
71
|
return finalConfig;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import {PluginOption} from 'vite';
|
|
3
|
+
import type {IndexInput, Indexer} from '@storybook/types';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import {DuckDBConnection} from '@malloydata/db-duckdb';
|
|
6
|
+
import {Model, SingleConnectionRuntime, URLReader} from '@malloydata/malloy';
|
|
7
|
+
|
|
8
|
+
const STORY_MODEL_PREFIX = /##\(story\)\s/;
|
|
9
|
+
const STORY_PREFIX = /#\(story\)\s/;
|
|
10
|
+
|
|
11
|
+
async function createConnection() {
|
|
12
|
+
// TODO: figure out how to get duckdb.table to load based on taht path, rather than from workingDirectory. so that malloy story files can be anywhere
|
|
13
|
+
const workingDirectory = path.join(__dirname, '../src/stories');
|
|
14
|
+
const connection = new DuckDBConnection(
|
|
15
|
+
'duckdb',
|
|
16
|
+
undefined,
|
|
17
|
+
workingDirectory,
|
|
18
|
+
{
|
|
19
|
+
rowLimit: 1000,
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
await connection.connecting;
|
|
23
|
+
return connection;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function getMaterializedModel(fileName: string) {
|
|
27
|
+
const connection = await createConnection();
|
|
28
|
+
const modelCode = fs.readFileSync(fileName, 'utf-8');
|
|
29
|
+
const runtime = new SingleConnectionRuntime(connection);
|
|
30
|
+
const model = runtime.loadModel(modelCode);
|
|
31
|
+
|
|
32
|
+
const materializedModel = await model.getModel();
|
|
33
|
+
return materializedModel;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type ModelIndexInput = IndexInput & {
|
|
37
|
+
sourceName: string;
|
|
38
|
+
queryName: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function fileNameToComponentName(fileName: string) {
|
|
42
|
+
const regex = /\/([^\/]+)\.stories\.malloy$/;
|
|
43
|
+
const match = fileName.match(regex);
|
|
44
|
+
const name = match && match[1];
|
|
45
|
+
if (name) {
|
|
46
|
+
return name
|
|
47
|
+
.split(/[-_]/)
|
|
48
|
+
.map(part => {
|
|
49
|
+
return part.charAt(0).toUpperCase() + part.slice(1);
|
|
50
|
+
})
|
|
51
|
+
.join(' ');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function getModelStories(materializedModel: Model, fileName: string) {
|
|
56
|
+
const models = materializedModel.explores;
|
|
57
|
+
let modelStories: ModelIndexInput[] = [];
|
|
58
|
+
|
|
59
|
+
const isLegacy = materializedModel.tagParse().tag.has('renderer_legacy');
|
|
60
|
+
const componentName =
|
|
61
|
+
materializedModel
|
|
62
|
+
.tagParse({prefix: STORY_MODEL_PREFIX})
|
|
63
|
+
.tag.text('component') ?? fileNameToComponentName(fileName);
|
|
64
|
+
|
|
65
|
+
models.forEach(model => {
|
|
66
|
+
model.allFields
|
|
67
|
+
.filter(f => f.isQueryField() && f.getTaglines(STORY_PREFIX).length > 0)
|
|
68
|
+
.forEach(query => {
|
|
69
|
+
modelStories.push({
|
|
70
|
+
type: 'story',
|
|
71
|
+
importPath: fileName,
|
|
72
|
+
title: `Malloy ${isLegacy ? 'Legacy' : 'Next'}/${componentName}`,
|
|
73
|
+
exportName: query.name,
|
|
74
|
+
name: query.tagParse({prefix: STORY_PREFIX}).tag.text('story'),
|
|
75
|
+
sourceName: model.name,
|
|
76
|
+
queryName: query.name,
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
componentName,
|
|
82
|
+
isLegacy,
|
|
83
|
+
stories: modelStories,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const malloyStoriesIndexer: Indexer = {
|
|
88
|
+
test: /stories\.malloy$/,
|
|
89
|
+
createIndex: async fileName => {
|
|
90
|
+
const connection = await createConnection();
|
|
91
|
+
const modelCode = fs.readFileSync(fileName, 'utf-8');
|
|
92
|
+
const urlReader: URLReader = {
|
|
93
|
+
async readURL(url) {
|
|
94
|
+
const pathToUrl = path.join(fileName, '..', url.href);
|
|
95
|
+
const contents = fs.readFileSync(pathToUrl, 'utf-8');
|
|
96
|
+
return contents;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
const runtime = new SingleConnectionRuntime(urlReader, connection);
|
|
100
|
+
const model = runtime.loadModel(modelCode);
|
|
101
|
+
const materializedModel = await model.getModel();
|
|
102
|
+
const modelStories = getModelStories(materializedModel, fileName).stories;
|
|
103
|
+
return modelStories;
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export function viteMalloyStoriesPlugin(): PluginOption {
|
|
108
|
+
return {
|
|
109
|
+
name: 'vite-plugin-storybook-malloy-stories',
|
|
110
|
+
async transform(code, id) {
|
|
111
|
+
if (id.endsWith('.stories.malloy')) {
|
|
112
|
+
const model = await getMaterializedModel(id);
|
|
113
|
+
const modelStoriesMeta = getModelStories(model, id);
|
|
114
|
+
|
|
115
|
+
const storyExports = modelStoriesMeta.stories
|
|
116
|
+
.map(
|
|
117
|
+
meta => `
|
|
118
|
+
export const ${meta.exportName} = {
|
|
119
|
+
args: {
|
|
120
|
+
source: '${meta.sourceName}',
|
|
121
|
+
view: '${meta.queryName}',
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
`
|
|
125
|
+
)
|
|
126
|
+
.join('\n');
|
|
127
|
+
|
|
128
|
+
const header = modelStoriesMeta.isLegacy
|
|
129
|
+
? `
|
|
130
|
+
import script from '${id}?raw';
|
|
131
|
+
import {renderMalloyLegacy} from './util';
|
|
132
|
+
|
|
133
|
+
export default {
|
|
134
|
+
title: 'Malloy Legacy/Basic',
|
|
135
|
+
render: ({source, view}, {globals: {getConnection}}) => {
|
|
136
|
+
return renderMalloyLegacy({script, source, view, connection: getConnection()});
|
|
137
|
+
},
|
|
138
|
+
argTypes: {},
|
|
139
|
+
};`
|
|
140
|
+
: `
|
|
141
|
+
import script from '${id}?raw';
|
|
142
|
+
import {createLoader} from './util';
|
|
143
|
+
import './themes.css';
|
|
144
|
+
import '../component/render-webcomponent';
|
|
145
|
+
|
|
146
|
+
const meta = {
|
|
147
|
+
title: "Malloy Next/${modelStoriesMeta.componentName}",
|
|
148
|
+
render: ({classes}, context) => {
|
|
149
|
+
const parent = document.createElement('div');
|
|
150
|
+
parent.style.height = 'calc(100vh - 40px)';
|
|
151
|
+
parent.style.position = 'relative';
|
|
152
|
+
const el = document.createElement('malloy-render');
|
|
153
|
+
if (classes) el.classList.add(classes);
|
|
154
|
+
el.result = context.loaded['result'];
|
|
155
|
+
parent.appendChild(el);
|
|
156
|
+
return parent;
|
|
157
|
+
},
|
|
158
|
+
loaders: [createLoader(script)],
|
|
159
|
+
argTypes: {},
|
|
160
|
+
};
|
|
161
|
+
export default meta;
|
|
162
|
+
`;
|
|
163
|
+
|
|
164
|
+
const generatedCode = `
|
|
165
|
+
${header}
|
|
166
|
+
${storyExports}
|
|
167
|
+
`;
|
|
168
|
+
return generatedCode;
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
package/.storybook/preview.ts
CHANGED
|
@@ -3,7 +3,9 @@ import {Preview} from '@storybook/html';
|
|
|
3
3
|
import registeredData from './registered_data.json';
|
|
4
4
|
import theme from './theme';
|
|
5
5
|
|
|
6
|
+
let memoConnection: DuckDBWASMConnection | null = null;
|
|
6
7
|
async function createConnection() {
|
|
8
|
+
if (memoConnection) return memoConnection;
|
|
7
9
|
const connection = new DuckDBWASMConnection('duckdb', null, undefined, {
|
|
8
10
|
rowLimit: 1000,
|
|
9
11
|
});
|
|
@@ -15,12 +17,15 @@ async function createConnection() {
|
|
|
15
17
|
new window.URL(fullTableName, window.location.href).toString()
|
|
16
18
|
);
|
|
17
19
|
}
|
|
20
|
+
memoConnection = connection;
|
|
18
21
|
return connection;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
const preview: Preview = {
|
|
22
25
|
parameters: {
|
|
23
|
-
actions: {
|
|
26
|
+
actions: {
|
|
27
|
+
// argTypesRegex: '^on[A-Z].*'
|
|
28
|
+
},
|
|
24
29
|
controls: {
|
|
25
30
|
matchers: {
|
|
26
31
|
color: /(background|color)$/i,
|
|
@@ -31,8 +36,10 @@ const preview: Preview = {
|
|
|
31
36
|
theme,
|
|
32
37
|
},
|
|
33
38
|
},
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
initialGlobals: {
|
|
40
|
+
// Doing this with a lazy callback in the context because otherwise
|
|
41
|
+
// Storybook was providing an empty Promise on first render when trying to directly createConnection here
|
|
42
|
+
getConnection: () => createConnection(),
|
|
36
43
|
},
|
|
37
44
|
};
|
|
38
45
|
|