diff --git a/build/embed-packager.js b/build/embed-packager.js index 4c09777ef..1f5fb5e9d 100644 --- a/build/embed-packager.js +++ b/build/embed-packager.js @@ -132,13 +132,11 @@ module.exports = function (ret, pack, settings, opt) { } catch (e) { d = (/((?:https?|file)\:.*)$/.test(e.stack) && RegExp.$1).replace(/\\/[^\\/]*$/, ''); } - ${contents.replace(/\"url\"\s*\:\s*('|")(\.\/.*)\1/g, function ( - _, - quote, - value - ) { - return `"url": d + ${quote}${value.substring(1)}${quote}`; - })} + ${contents + .replace(/\"url\"\s*\:\s*('|")(\.\/.*)\1/g, function (_, quote, value) { + return `"url": d + ${quote}${value.substring(1)}${quote}`; + }) + .replace(/require\.resourceMap/, 'amis.require.resourceMap')} })()`; } diff --git a/docs/intro.md b/docs/intro.md index d92019aa6..640b66764 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -178,7 +178,7 @@ amis 是一个前端低代码框架,它使用 JSON 配置来生成页面,可 ## amis 的其它亮点 -- **提供完整的界面解决方案**,其它 UI 框架必须使用 JavaScript 来组装业务逻辑,而 amis 只需 JSON 配置就能完整完整功能开发,包括数据获取、表单提交及验证等功能。 +- **提供完整的界面解决方案**,其它 UI 框架必须使用 JavaScript 来组装业务逻辑,而 amis 只需 JSON 配置就能完成完整功能开发,包括数据获取、表单提交及验证等功能。 - 内置 **92** 种 UI 组件,包括其它 UI 框架都会不提供的富文本编辑器、代码编辑器等,能满足各种页面组件展现的需求,而且对于特殊的展现形式还可以通过[自定义组件](./custom.md)来扩充。 - 容器组件支持**无限层级嵌套**,可以通过组合来满足各种布局需求。 - 经历了长时间的实战考验,amis 在百度内部得到了广泛使用,在 4 年多的时间里创建了 3w 多页面,从内容审核到机器管理,从数据分析到模型训练,amis 满足了各种各样的页面需求。 diff --git a/examples/components/IFrame.jsx b/examples/components/IFrame.jsx index 6d8ddf4be..d69f2c199 100644 --- a/examples/components/IFrame.jsx +++ b/examples/components/IFrame.jsx @@ -24,7 +24,7 @@ export default { { type: 'iframe', className: 'b-a', - src: 'https://www.baidu.com/s?wd=${keywords|url_encode}', + src: 'https://www.baidu.com/s?wd=${keywords|raw}', height: 500 } ] diff --git a/examples/loader.ts b/examples/loader.ts index b0c640942..d5664223c 100644 --- a/examples/loader.ts +++ b/examples/loader.ts @@ -30,7 +30,7 @@ function amisRequire(...args: Array) { let id = args.shift(); id = Array.isArray(id) ? id.map(id => mapping[id] || id) : mapping[id] || id; args.unshift(id); - return require.apply(this, args); + return amis.require.apply(this, args); } (window as any).amisRequire = amisRequire; diff --git a/examples/sdk-mod.js b/examples/sdk-mod.js index b60daea29..35ae95b01 100644 --- a/examples/sdk-mod.js +++ b/examples/sdk-mod.js @@ -1,292 +1,265 @@ /** - * @file: mod.js - * @author fis - * ver: 1.0.13 - * update: 2016/01/27 - * https://github.com/fex-team/mod + * @file mod-sandbox.js. */ -var require; - -/* eslint-disable no-unused-vars */ -var define; +/* eslint-disable */ (function (global) { + var require, define; + var amis = window.amis || {}; - var amis = window.amis || {}; - // 避免重复加载而导致已定义模块丢失 - if (require) { - return; + // 避免重复加载而导致已定义模块丢失 + if (amis.require) { + return; + } + + var head = document.getElementsByTagName('head')[0]; + var loadingMap = {}; + var factoryMap = {}; + var modulesMap = {}; + var scriptsMap = {}; + var resMap = {}; + var pkgMap = {}; + + var createScripts = function (queues, onerror) { + var docFrag = document.createDocumentFragment(); + + for (var i = 0, len = queues.length; i < len; i++) { + var id = queues[i].id; + var url = queues[i].url; + + if (url in scriptsMap) { + continue; + } + + scriptsMap[url] = true; + + var script = document.createElement('script'); + if (onerror) { + (function (script, id) { + var tid = setTimeout(function () { + onerror(id); + }, require.timeout); + + script.onerror = function () { + clearTimeout(tid); + onerror(id); + }; + + var onload = function () { + clearTimeout(tid); + }; + + if ('onload' in script) { + script.onload = onload; + } else { + script.onreadystatechange = function () { + if ( + this.readyState === 'loaded' || + this.readyState === 'complete' + ) { + onload(); + } + }; + } + })(script, id); + } + script.type = 'text/javascript'; + script.src = url; + + docFrag.appendChild(script); } - var head = document.getElementsByTagName('head')[0]; - var loadingMap = {}; - var factoryMap = {}; - var modulesMap = {}; - var scriptsMap = {}; - var resMap = {}; - var pkgMap = {}; + head.appendChild(docFrag); + }; - var createScripts = function (queues, onerror) { + var loadScripts = function (ids, callback, onerror) { + var queues = []; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + var queue = loadingMap[id] || (loadingMap[id] = []); + queue.push(callback); - var docFrag = document.createDocumentFragment(); + // + // resource map query + // + var res = resMap[id] || resMap[id + '.js'] || {}; + var pkg = res.pkg; + var url; - for (var i = 0, len = queues.length; i < len; i++) { - var id = queues[i].id; - var url = queues[i].url; + if (pkg) { + url = pkgMap[pkg].url || pkgMap[pkg].uri; + } else { + url = res.url || res.uri || id; + } - if (url in scriptsMap) { - continue; - } + queues.push({ + id: id, + url: url + }); + } - scriptsMap[url] = true; + createScripts(queues, onerror); + }; - var script = document.createElement('script'); - if (onerror) { - (function (script, id) { - var tid = setTimeout(function () { - onerror(id); - }, require.timeout); + define = function (id, factory) { + id = id.replace(/\.js$/i, ''); + factoryMap[id] = factory; - script.onerror = function () { - clearTimeout(tid); - onerror(id); - }; + var queue = loadingMap[id]; + if (queue) { + for (var i = 0, n = queue.length; i < n; i++) { + queue[i](); + } + delete loadingMap[id]; + } + }; - var onload = function () { - clearTimeout(tid); - }; + require = function (id) { + // compatible with require([dep, dep2...]) syntax. + if (id && id.splice) { + return require.async.apply(this, arguments); + } - if ('onload' in script) { - script.onload = onload; - } - else { - script.onreadystatechange = function () { - if (this.readyState === 'loaded' || this.readyState === 'complete') { - onload(); - } - }; - } - })(script, id); - } - script.type = 'text/javascript'; - script.src = url; + id = require.alias(id); - docFrag.appendChild(script); - } + var mod = modulesMap[id]; + if (mod) { + return mod.exports; + } - head.appendChild(docFrag); + // + // init module + // + var factory = factoryMap[id]; + if (!factory) { + throw '[ModJS] Cannot find module `' + id + '`'; + } + + mod = modulesMap[id] = { + exports: {} }; - var loadScripts = function (ids, callback, onerror) { - var queues = []; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; - var queue = loadingMap[id] || (loadingMap[id] = []); - queue.push(callback); + // + // factory: function OR value + // + var ret = + typeof factory === 'function' + ? factory.apply(mod, [require, mod.exports, mod]) + : factory; - // - // resource map query - // - var res = resMap[id] || resMap[id + '.js'] || {}; - var pkg = res.pkg; - var url; + if (ret) { + mod.exports = ret; + } - if (pkg) { - url = pkgMap[pkg].url || pkgMap[pkg].uri; - } - else { - url = res.url || res.uri || id; - } + return mod.exports; + }; - queues.push({ - id: id, - url: url - }); - } + require.async = function (names, onload, onerror) { + if (typeof names === 'string') { + names = [names]; + } - createScripts(queues, onerror); - }; + var needMap = {}; + var needNum = 0; + var needLoad = []; - define = function (id, factory) { - id = id.replace(/\.js$/i, ''); - factoryMap[id] = factory; - - var queue = loadingMap[id]; - if (queue) { - for (var i = 0, n = queue.length; i < n; i++) { - queue[i](); - } - delete loadingMap[id]; - } - }; - - require = function (id) { - - // compatible with require([dep, dep2...]) syntax. - if (id && id.splice) { - return require.async.apply(this, arguments); - } - - id = require.alias(id); - - var mod = modulesMap[id]; - if (mod) { - return mod.exports; - } + function findNeed(depArr) { + var child; + for (var i = 0, n = depArr.length; i < n; i++) { // - // init module + // skip loading or loaded // - var factory = factoryMap[id]; - if (!factory) { - throw '[ModJS] Cannot find module `' + id + '`'; + var dep = require.alias(depArr[i]); + + if (dep in needMap) { + continue; } - mod = modulesMap[id] = { - exports: {} - }; + needMap[dep] = true; - // - // factory: function OR value - // - var ret = (typeof factory === 'function') ? factory.apply(mod, [require, mod.exports, mod]) : factory; - - if (ret) { - mod.exports = ret; + if (dep in factoryMap) { + // check whether loaded resource's deps is loaded or not + child = resMap[dep] || resMap[dep + '.js']; + if (child && 'deps' in child) { + findNeed(child.deps); + } + continue; } - return mod.exports; - }; + needLoad.push(dep); + needNum++; - require.async = function (names, onload, onerror) { - if (typeof names === 'string') { - names = [names]; + child = resMap[dep] || resMap[dep + '.js']; + if (child && 'deps' in child) { + findNeed(child.deps); + } + } + } + + function updateNeed() { + if (0 === needNum--) { + var args = []; + for (var i = 0, n = names.length; i < n; i++) { + args[i] = require(names[i]); } - var needMap = {}; - var needNum = 0; - var needLoad = []; + onload && onload.apply(global, args); + } + } - function findNeed(depArr) { - var child; + findNeed(names); + loadScripts(needLoad, updateNeed, onerror); + updateNeed(); + }; - for (var i = 0, n = depArr.length; i < n; i++) { - // - // skip loading or loaded - // - var dep = require.alias(depArr[i]); + require.ensure = function (names, callback) { + require.async(names, function () { + callback && callback.call(this, require); + }); + }; - if (dep in needMap) { - continue; - } + require.resourceMap = function (obj) { + var k; + var col; - needMap[dep] = true; + // merge `res` & `pkg` fields + col = obj.res; + for (k in col) { + if (col.hasOwnProperty(k)) { + resMap[k] = col[k]; + } + } - if (dep in factoryMap) { - // check whether loaded resource's deps is loaded or not - child = resMap[dep] || resMap[dep + '.js']; - if (child && 'deps' in child) { - findNeed(child.deps); - } - continue; - } + col = obj.pkg; + for (k in col) { + if (col.hasOwnProperty(k)) { + pkgMap[k] = col[k]; + } + } + }; - needLoad.push(dep); - needNum++; + require.loadJs = function (url) { + if (url in scriptsMap) { + return; + } - child = resMap[dep] || resMap[dep + '.js']; - if (child && 'deps' in child) { - findNeed(child.deps); - } - } - } + scriptsMap[url] = true; - function updateNeed() { - if (0 === needNum--) { - var args = []; - for (var i = 0, n = names.length; i < n; i++) { - args[i] = require(names[i]); - } + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = url; + head.appendChild(script); + }; - onload && onload.apply(global, args); - } - } + require.alias = function (id) { + return id.replace(/\.js$/i, ''); + }; - findNeed(names); - loadScripts(needLoad, updateNeed, onerror); - updateNeed(); - }; - - require.ensure = function (names, callback) { - require.async(names, function () { - callback && callback.call(this, require); - }); - }; - - require.resourceMap = function (obj) { - var k; - var col; - - // merge `res` & `pkg` fields - col = obj.res; - for (k in col) { - if (col.hasOwnProperty(k)) { - resMap[k] = col[k]; - } - } - - col = obj.pkg; - for (k in col) { - if (col.hasOwnProperty(k)) { - pkgMap[k] = col[k]; - } - } - }; - - require.loadJs = function (url) { - if (url in scriptsMap) { - return; - } - - scriptsMap[url] = true; - - var script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = url; - head.appendChild(script); - }; - - require.loadCss = function (cfg) { - if (cfg.content) { - var sty = document.createElement('style'); - sty.type = 'text/css'; - - if (sty.styleSheet) { // IE - sty.styleSheet.cssText = cfg.content; - } - else { - sty.innerHTML = cfg.content; - } - head.appendChild(sty); - } - else if (cfg.url) { - var link = document.createElement('link'); - link.href = cfg.url; - link.rel = 'stylesheet'; - link.type = 'text/css'; - head.appendChild(link); - } - }; - - - require.alias = function (id) { - return id.replace(/\.js$/i, ''); - }; - - require.timeout = 5000; - - amis.require = require; - amis.define = define; - window.amis = amis; + require.timeout = 5000; + amis.require = require; + amis.define = define; + window.amis = amis; + // window.require = window.require || require; })(this); diff --git a/scss/_variables.scss b/scss/_variables.scss index f67dd9642..d64c24c70 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -512,6 +512,7 @@ $Card-actions-borderColor: lighten($Card-borderColor, 5%) !default; $Card-actions-onHover-bg: darken($white, 5%) !default; $Card-actions-onHover-color: darken($text-color, 5%) !default; $Card-actions-onChecked-onHover-bg: darken(#d9f3fb, 5%) !default; +$Card-actions-fontSize: $fontSizeBase !default; $Card-onChecked-bg: #d9f3fb !default; $Card-onChecked-borderColor: darken($Table-onChecked-bg, 10%) !default; diff --git a/scss/components/_card.scss b/scss/components/_card.scss index fd2ad89aa..7b2968f46 100644 --- a/scss/components/_card.scss +++ b/scss/components/_card.scss @@ -144,7 +144,7 @@ color: $text-color; text-align: center; line-height: px2rem(40px); - // font-size: $fontSizeBase; + font-size: $Card-actions-fontSize; &:not(.is-disabled) { cursor: pointer; diff --git a/scss/components/_list.scss b/scss/components/_list.scss index 75319c299..e18e6fdb6 100644 --- a/scss/components/_list.scss +++ b/scss/components/_list.scss @@ -78,7 +78,7 @@ &-placeholder { color: $text--muted-color; text-align: center; - height: $List-placeholder-height; + min-height: $List-placeholder-height; line-height: $List-placeholder-height; } } diff --git a/scss/components/_result-box.scss b/scss/components/_result-box.scss index dacc04b60..7bd219add 100644 --- a/scss/components/_result-box.scss +++ b/scss/components/_result-box.scss @@ -10,7 +10,9 @@ background-color: $Form-input-onError-bg; } - &.is-focused { + &.is-focused, + &:focus { + outline: none; border-color: $Form-input-onFocused-borderColor; box-shadow: $Form-input-boxShadow; diff --git a/scss/themes/cxd.scss b/scss/themes/cxd.scss index 884237621..c9d38b682 100644 --- a/scss/themes/cxd.scss +++ b/scss/themes/cxd.scss @@ -454,6 +454,9 @@ $Card-actions-onHover-bg: white; $Card-actions-onHover-color: $primary; $Card-actions-onChecked-onHover-bg: $white; +$Card-actions-borderColor: lighten($borderColor, 2.5%); +$Card-actions-fontSize: px2rem(12px); + // Combo $Combo--horizontal-dragger-top: px2rem(5px); diff --git a/src/Scoped.tsx b/src/Scoped.tsx index cc74b97c8..11b20482e 100644 --- a/src/Scoped.tsx +++ b/src/Scoped.tsx @@ -168,16 +168,17 @@ function createScopedTools( * * @param target 目标 name */ - close(target: string) { + close(target: string | boolean) { const scoped = this; - let targets = - typeof target === 'string' ? target.split(/\s*,\s*/) : target; - // 过滤已经关掉的,当用户 close 配置多个弹框 name 时会出现这种情况 - targets - .map(name => scoped.getComponentByName(name)) - .filter(component => component && component.props.show) - .forEach(closeDialog); + if (typeof target === 'string') { + // 过滤已经关掉的,当用户 close 配置多个弹框 name 时会出现这种情况 + target + .split(/\s*,\s*/) + .map(name => scoped.getComponentByName(name)) + .filter(component => component && component.props.show) + .forEach(closeDialog); + } } }; } diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx index 3b4ba396d..96ab750e6 100644 --- a/src/components/Alert.tsx +++ b/src/components/Alert.tsx @@ -9,6 +9,9 @@ import Modal from './Modal'; import Button from './Button'; import {ClassNamesFn, themeable, ThemeProps} from '../theme'; import {LocaleProps, localeable} from '../locale'; +import Html from './Html'; +import {PlainObject} from '../types'; +import {render as renderSchema} from '../factory'; export interface AlertProps extends ThemeProps, LocaleProps { container?: any; @@ -24,6 +27,9 @@ export interface AlertState { title?: string; content: string; confirm: boolean; + prompt?: boolean; + controls?: any; + value?: any; confirmText?: string; } @@ -57,7 +63,8 @@ export class Alert extends React.Component { this.handleConfirm = this.handleConfirm.bind(this); this.handleCancel = this.handleCancel.bind(this); this.modalRef = this.modalRef.bind(this); - this.bodyRef = this.bodyRef.bind(this); + this.handleFormSubmit = this.handleFormSubmit.bind(this); + this.scopeRef = this.scopeRef.bind(this); } static defaultProps = { @@ -86,8 +93,19 @@ export class Alert extends React.Component { Alert.instance = null; } + schemaSope: any; + scopeRef(schemaSope: any) { + this.schemaSope = schemaSope; + } + handleConfirm() { - this.close(true); + const form = this.schemaSope?.getComponentByName('form'); + + if (form) { + form.doAction({type: 'submit'}); + } else { + this.close(true); + } } handleCancel() { @@ -95,7 +113,7 @@ export class Alert extends React.Component { } close(confirmed: boolean) { - const isConfirm = this.state.confirm; + const isConfirm = this.state.confirm || this.state.prompt; this.setState( { @@ -128,13 +146,51 @@ export class Alert extends React.Component { }); } + prompt( + controls: any, + defaultValue?: any, + title: string = '请输入', + confirmText: string = '确认' + ) { + if (typeof controls === 'string') { + // 兼容浏览器标准用法。 + controls = [ + { + name: 'text', + label: controls, + type: 'text' + } + ]; + + if (typeof defaultValue === 'string') { + defaultValue = { + text: defaultValue + }; + } + } else if (!Array.isArray(controls)) { + controls = [controls]; + } + + this.setState({ + title, + controls, + show: true, + prompt: true, + value: defaultValue, + confirmText + }); + + return new Promise(resolve => { + this._resolve = resolve; + }); + } + modalRef(ref: any) { this._modal = ref; } - bodyRef(ref: any) { - this._body = ref; - this._body && (this._body.innerHTML = this.state.content); + handleFormSubmit(values: any) { + this.close(values); } render() { @@ -146,9 +202,11 @@ export class Alert extends React.Component { confirmBtnLevel, alertBtnLevel, classnames: cx, - classPrefix + theme } = this.props; const __ = this.props.translate; + const finalTitle = __(this.state.title ?? title); + const finalConfirmText = __(this.state.confirmText ?? confirmText); return ( { onHide={this.handleCancel} container={container} ref={this.modalRef} + closeOnEsc > -
-
- {__(this.state.title || title)} + {finalTitle ? ( +
+
{finalTitle}
-
+ ) : null}
-
-
-
- {this.state.confirm ? ( - - ) : null} - + {this.state.prompt ? ( + renderForm( + this.state.controls, + this.state.value, + this.handleFormSubmit, + this.scopeRef, + theme + ) + ) : ( + + )}
+ {finalConfirmText ? ( +
+ {this.state.confirm || this.state.prompt ? ( + + ) : null} + +
+ ) : null} ); } } +function renderForm( + controls: Array, + value: PlainObject = {}, + callback?: (values: PlainObject) => void, + scopeRef?: (value: any) => void, + theme?: string +) { + return renderSchema( + { + name: 'form', + type: 'form', + wrapWithPanel: false, + mode: 'horizontal', + controls + }, + { + data: value, + onFinished: callback, + scopeRef, + theme + }, + { + session: 'prompt' + } + ); +} + export const alert: (content: string, title?: string) => void = ( content, title @@ -191,5 +293,12 @@ export const confirm: ( confirmText?: string ) => Promise = (content, title, confirmText) => Alert.getInstance().confirm(content, title, confirmText); +export const prompt: ( + controls: any, + defaultvalue?: any, + title?: string, + confirmText?: string +) => Promise = (controls, defaultvalue, title, confirmText) => + Alert.getInstance().prompt(controls, defaultvalue, title, confirmText); export const FinnalAlert = themeable(localeable(Alert)); export default FinnalAlert; diff --git a/src/components/index.tsx b/src/components/index.tsx index 574f5861e..cd929dfdd 100644 --- a/src/components/index.tsx +++ b/src/components/index.tsx @@ -5,7 +5,7 @@ */ import NotFound from './404'; -import {default as Alert, alert, confirm} from './Alert'; +import {default as Alert, alert, confirm, prompt} from './Alert'; import {default as ContextMenu, openContextMenus} from './ContextMenu'; import AsideNav from './AsideNav'; import Button from './Button'; @@ -57,10 +57,11 @@ export { NotFound, Alert as AlertComponent, alert, + confirm, + prompt, ContextMenu, openContextMenus, Alert2, - confirm, AsideNav, Button, Checkbox, diff --git a/src/renderers/CRUD.tsx b/src/renderers/CRUD.tsx index 45dac906d..d5fa3aedb 100644 --- a/src/renderers/CRUD.tsx +++ b/src/renderers/CRUD.tsx @@ -443,7 +443,7 @@ export default class CRUD extends React.Component { action.reload ? this.reloadTarget(action.reload, data) - : this.search({[pageField || 'page']: 1}, undefined, true); + : this.search({[pageField || 'page']: 1}, undefined, true, true); action.close && this.closeTarget(action.close); const redirect = action.redirect && filter(action.redirect, data); diff --git a/src/renderers/Form/index.tsx b/src/renderers/Form/index.tsx index e7bb633f4..1fdbf67c6 100644 --- a/src/renderers/Form/index.tsx +++ b/src/renderers/Form/index.tsx @@ -460,6 +460,18 @@ export default class Form extends React.Component { return store.clearErrors(); } + getValues() { + const {store} = this.props; + this.flush(); + return store.data; + } + + setValues(value: any) { + const {store} = this.props; + this.flush(); + store.setValues(value); + } + submit(fn?: (values: object) => Promise): Promise { const {store, messages, translate: __} = this.props; this.flush(); @@ -1219,7 +1231,11 @@ export class FormRenderer extends Form { super.componentWillUnmount(); } - doAction(action: Action, data: object, throwErrors: boolean = false) { + doAction( + action: Action, + data: object = this.props.store.data, + throwErrors: boolean = false + ) { return this.handleAction(undefined, action, data, throwErrors); } diff --git a/src/renderers/List.tsx b/src/renderers/List.tsx index da8a501c7..8608162be 100644 --- a/src/renderers/List.tsx +++ b/src/renderers/List.tsx @@ -789,7 +789,9 @@ export default class List extends React.Component { )}
) : ( -
{__(placeholder)}
+
+ {render('placeholder', __(placeholder))} +
)} {this.renderFooter()} diff --git a/src/renderers/Status.tsx b/src/renderers/Status.tsx index fc2e63ec2..cbce18f69 100644 --- a/src/renderers/Status.tsx +++ b/src/renderers/Status.tsx @@ -72,6 +72,7 @@ export class StatusField extends React.Component { ); } else if (itemClassName) { diff --git a/src/theme.tsx b/src/theme.tsx index 12f294683..f106cfcd5 100644 --- a/src/theme.tsx +++ b/src/theme.tsx @@ -120,10 +120,11 @@ export interface ThemeProps { className?: string; classPrefix: string; classnames: ClassNamesFn; + theme?: string; } -export const ThemeContext = React.createContext('theme'); export let defaultTheme: string = 'default'; +export const ThemeContext = React.createContext(''); export function themeable< T extends React.ComponentType & ThemeProps> & { @@ -156,9 +157,11 @@ export function themeable< const injectedProps: { classPrefix: string; classnames: ClassNamesFn; + theme: string; } = { classPrefix: config.classPrefix as string, - classnames: config.classnames + classnames: config.classnames, + theme }; return ( diff --git a/src/types.ts b/src/types.ts index 28d6497a8..6dd9ad42c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,7 +7,7 @@ export interface ApiObject { withCredentials?: boolean; cancelExecutor?: (cancel: Function) => void; }; - autoRefresh: boolean; // 是否自动刷新,当 url 中的取值结果变化时,自动刷新数据。 + autoRefresh?: boolean; // 是否自动刷新,当 url 中的取值结果变化时,自动刷新数据。 reload?: string; sendOn?: string; adaptor?: (payload: object, response: fetcherResult, api: ApiObject) => any; diff --git a/src/utils/api.ts b/src/utils/api.ts index cb86c439b..bfc0e57d9 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -253,7 +253,10 @@ export function isApiOutdated( } export function isValidApi(api: string) { - return api && /^(?:https?:\/\/[^\/]+)?(\/[^\s\/\?]*){1,}(\?.*)?$/.test(api); + return ( + api && + /^(?:(https?|wss?|taf):\/\/[^\/]+)?(\/[^\s\/\?]*){1,}(\?.*)?$/.test(api) + ); } export function isEffectiveApi( diff --git a/src/utils/tpl-builtin.ts b/src/utils/tpl-builtin.ts index d88e30581..2d31cb0bc 100644 --- a/src/utils/tpl-builtin.ts +++ b/src/utils/tpl-builtin.ts @@ -42,7 +42,7 @@ const entityMap: { '/': '/' }; export const escapeHtml = (str: string) => - String(str).replace(/[&<>"'\/]/g, function(s) { + String(str).replace(/[&<>"'\/]/g, function (s) { return entityMap[s]; }); @@ -218,13 +218,13 @@ export const filters: { Array.isArray(input) ? input.map(item => resolveVariable(path, item) || item) : resolveVariable(path, input) || input, - str2date: function(input, inputFormat = 'X', outputFormat = 'X') { + str2date: function (input, inputFormat = 'X', outputFormat = 'X') { return input ? filterDate(input, this, inputFormat).format(outputFormat) : ''; }, asArray: input => (Array.isArray(input) ? input : input ? [input] : input), - filter: function(input, keys, expOrDirective, arg1) { + filter: function (input, keys, expOrDirective, arg1) { if (!Array.isArray(input) || !keys || !expOrDirective) { return input; } @@ -243,7 +243,7 @@ export const filters: { fn = value => arg1 == value; } else if (directive === 'isIn') { let list: Array = arg1 ? getStrOrVariable(arg1, this) : []; - list = Array.isArray(list) ? list : []; + list = Array.isArray(list) ? list : [list]; fn = value => !!~list.indexOf(value); } else if (directive === 'notIn') { let list: Array = arg1 ? getStrOrVariable(arg1, this) : []; @@ -284,7 +284,7 @@ export const filters: { return decodeURIComponent( atob(str) .split('') - .map(function(c) { + .map(function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }) .join('')