@ember-eui/core 5.7.0 → 5.8.0
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/addon/components/eui-i18n/index.hbs +33 -0
- package/addon/components/eui-i18n/index.ts +73 -0
- package/addon/components/eui-i18n/render.hbs +1 -0
- package/addon/components/eui-i18n/util.ts +127 -0
- package/addon/components/eui-pagination/button-wrapper/index.hbs +21 -0
- package/addon/components/eui-pagination/index.hbs +115 -0
- package/addon/components/eui-pagination/index.ts +177 -0
- package/addon/components/eui-pagination/next-button/index.hbs +27 -0
- package/addon/components/eui-pagination/previous-button/index.hbs +27 -0
- package/addon/components/eui-pagination-button/index.hbs +36 -0
- package/addon/i18n/index.ts +8 -0
- package/addon/utils/predicate/common_predicates.ts +37 -0
- package/addon/utils/predicate/index.ts +10 -0
- package/addon/utils/predicate/lodash_predicates.ts +27 -0
- package/app/components/eui-i18n/index.js +1 -0
- package/app/components/eui-i18n/render.js +1 -0
- package/app/components/eui-pagination/button-wrapper.js +1 -0
- package/app/components/eui-pagination/index.js +1 -0
- package/app/components/eui-pagination/next-button.js +1 -0
- package/app/components/eui-pagination/previous-button.js +1 -0
- package/app/components/eui-pagination-button/index.js +1 -0
- package/app/i18n/index.js +1 -0
- package/docs/navigation/pagination/demo/d01-basic.md +27 -0
- package/docs/navigation/pagination/index.md +8 -0
- package/docs/utilities/i18n/demo/d01-basic.md +32 -0
- package/docs/utilities/i18n/index.md +8 -0
- package/package.json +2 -2
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{{#let this.lookupedTokens as |result|}}
|
|
2
|
+
{{#if this.isI18nTokensShape}}
|
|
3
|
+
{{#if this.i18n.renderComponent}}
|
|
4
|
+
{{yield
|
|
5
|
+
(component
|
|
6
|
+
(ensure-safe-component this.i18n.renderComponent) tokens=result
|
|
7
|
+
)
|
|
8
|
+
}}
|
|
9
|
+
{{else}}
|
|
10
|
+
{{#each
|
|
11
|
+
(if (not-eq (type-of result) "array") (array result) result)
|
|
12
|
+
as |token index|
|
|
13
|
+
}}
|
|
14
|
+
{{yield (component "eui-i18n/render" token=token) index result}}
|
|
15
|
+
{{/each}}
|
|
16
|
+
{{/if}}
|
|
17
|
+
{{else}}
|
|
18
|
+
{{#if this.i18n.renderComponent}}
|
|
19
|
+
{{yield
|
|
20
|
+
(component
|
|
21
|
+
(ensure-safe-component this.i18n.renderComponent) tokens=result
|
|
22
|
+
)
|
|
23
|
+
}}
|
|
24
|
+
{{else}}
|
|
25
|
+
{{#each
|
|
26
|
+
(if (not-eq (type-of result) "array") (array result) result)
|
|
27
|
+
as |token index|
|
|
28
|
+
}}
|
|
29
|
+
{{yield (component "eui-i18n/render" token=token) index result}}
|
|
30
|
+
{{/each}}
|
|
31
|
+
{{/if}}
|
|
32
|
+
{{/if}}
|
|
33
|
+
{{/let}}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { processStringToChildren } from './util';
|
|
3
|
+
//@ts-ignore
|
|
4
|
+
import { i18n, I18nShape } from '@ember-eui/core/i18n';
|
|
5
|
+
|
|
6
|
+
interface Args {
|
|
7
|
+
tokens?: string[];
|
|
8
|
+
defaults?: string[];
|
|
9
|
+
token?: string;
|
|
10
|
+
default?: string;
|
|
11
|
+
values?: { [key: string]: any };
|
|
12
|
+
i18n?: I18nShape;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface lookupTokenOptions {
|
|
16
|
+
token: string;
|
|
17
|
+
i18nMapping: I18nShape['mapping'];
|
|
18
|
+
valueDefault: string;
|
|
19
|
+
i18nMappingFunc?: (token: string) => string;
|
|
20
|
+
values?: { [key: string]: any };
|
|
21
|
+
render?: I18nShape['render'];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function lookupToken(options: lookupTokenOptions) {
|
|
25
|
+
const {
|
|
26
|
+
token,
|
|
27
|
+
i18nMapping,
|
|
28
|
+
valueDefault,
|
|
29
|
+
i18nMappingFunc,
|
|
30
|
+
values = {}
|
|
31
|
+
} = options;
|
|
32
|
+
|
|
33
|
+
let renderable = (i18nMapping && i18nMapping[token]) || valueDefault;
|
|
34
|
+
|
|
35
|
+
const children = processStringToChildren(renderable, values, i18nMappingFunc);
|
|
36
|
+
if (typeof children === 'string') {
|
|
37
|
+
// likewise, `processStringToChildren` returns a string or ReactChild[] depending on
|
|
38
|
+
// the type of `values`, so we will make the assumption that the default value is correct.
|
|
39
|
+
return children;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// same reasons as above, we can't promise the transforms match the default's type
|
|
43
|
+
return children;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default class EuiI18nComponent extends Component<Args> {
|
|
47
|
+
get isI18nTokensShape() {
|
|
48
|
+
return this.args.tokens != null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get i18n() {
|
|
52
|
+
return this.args.i18n || i18n;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get lookupedTokens() {
|
|
56
|
+
if (this.isI18nTokensShape) {
|
|
57
|
+
return this.args.tokens?.map((token, idx) =>
|
|
58
|
+
lookupToken({
|
|
59
|
+
token,
|
|
60
|
+
i18nMapping: i18n.mapping,
|
|
61
|
+
valueDefault: this.args.defaults![idx]
|
|
62
|
+
})
|
|
63
|
+
);
|
|
64
|
+
} else {
|
|
65
|
+
return lookupToken({
|
|
66
|
+
token: this.args.token!,
|
|
67
|
+
i18nMapping: i18n.mapping,
|
|
68
|
+
valueDefault: this.args.default!,
|
|
69
|
+
values: this.args.values
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{yield @token}}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
5
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
6
|
+
* Side Public License, v 1.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
isBoolean,
|
|
11
|
+
isString,
|
|
12
|
+
isNumber,
|
|
13
|
+
isUndefined
|
|
14
|
+
} from '../../utils/predicate';
|
|
15
|
+
import { get } from '@ember/object';
|
|
16
|
+
import { assert } from '@ember/debug';
|
|
17
|
+
|
|
18
|
+
function isPrimitive(value: any) {
|
|
19
|
+
return (
|
|
20
|
+
isBoolean(value) || isString(value) || isNumber(value) || isUndefined(value)
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type Child = string | { propName: string };
|
|
25
|
+
|
|
26
|
+
function hasPropName(child: Child): child is { propName: string } {
|
|
27
|
+
return child
|
|
28
|
+
? typeof child === 'object' && child.hasOwnProperty('propName')
|
|
29
|
+
: false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isElement(value: any) {
|
|
33
|
+
return value.hasOwnProperty('propName') && !isPrimitive(value);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Replaces placeholder values in `input` with their matching value in `values`
|
|
38
|
+
* e.g. input:'Hello, {name}' will replace `{name}` with `values[name]`
|
|
39
|
+
* @param {string} input
|
|
40
|
+
* @param {RenderableValues} values
|
|
41
|
+
* @param {Function} i18nMappingFunc
|
|
42
|
+
* @returns {string | React.ReactChild[]}
|
|
43
|
+
*/
|
|
44
|
+
export function processStringToChildren(
|
|
45
|
+
input: string,
|
|
46
|
+
values: { [key: string]: any },
|
|
47
|
+
i18nMappingFunc?: (token: string) => string
|
|
48
|
+
): any[] | string {
|
|
49
|
+
const children: any[] = [];
|
|
50
|
+
|
|
51
|
+
let child: Child | undefined = { propName: '' };
|
|
52
|
+
|
|
53
|
+
function appendCharToChild(char: string) {
|
|
54
|
+
if (child === undefined) {
|
|
55
|
+
// starting a new string literal
|
|
56
|
+
child = char;
|
|
57
|
+
} else if (typeof child === 'string') {
|
|
58
|
+
// existing string literal
|
|
59
|
+
child = child + char;
|
|
60
|
+
} else if (hasPropName(child)) {
|
|
61
|
+
// adding to the propName of a values lookup
|
|
62
|
+
child.propName = child.propName + char;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function appendValueToChildren(value?: Child) {
|
|
67
|
+
if (value === undefined) {
|
|
68
|
+
return;
|
|
69
|
+
} else if (hasPropName(value)) {
|
|
70
|
+
// an array with any ReactElements will be kept as an array
|
|
71
|
+
// so they need to be assigned a key
|
|
72
|
+
// children.push(cloneElement(value, { key: children.length }));
|
|
73
|
+
children.push(value.propName);
|
|
74
|
+
} else if (isElement(value)) {
|
|
75
|
+
// this won't be called, propName children are converted to a ReactChild before calling this
|
|
76
|
+
} else {
|
|
77
|
+
// everything else can go straight in
|
|
78
|
+
if (i18nMappingFunc !== undefined && typeof value === 'string') {
|
|
79
|
+
value = i18nMappingFunc(value);
|
|
80
|
+
}
|
|
81
|
+
children.push(value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// if we don't encounter a non-primitive
|
|
86
|
+
// then `children` can be concatenated together at the end
|
|
87
|
+
let encounteredNonPrimitive = false;
|
|
88
|
+
for (let i = 0; i < input.length; i++) {
|
|
89
|
+
const char = input[i];
|
|
90
|
+
|
|
91
|
+
if (char === '\\') {
|
|
92
|
+
// peek at the next character to know if this is an escape
|
|
93
|
+
const nextChar = input[i + 1];
|
|
94
|
+
let charToAdd = char; // if this isn't an escape sequence then we will add the backslash
|
|
95
|
+
|
|
96
|
+
if (nextChar === '{' || nextChar === '}') {
|
|
97
|
+
// escaping a brace
|
|
98
|
+
i += 1; // advance passed the brace
|
|
99
|
+
charToAdd = input[i];
|
|
100
|
+
}
|
|
101
|
+
appendCharToChild(charToAdd);
|
|
102
|
+
} else if (char === '{') {
|
|
103
|
+
appendValueToChildren(child);
|
|
104
|
+
child = { propName: '' };
|
|
105
|
+
} else if (char === '}') {
|
|
106
|
+
const propName = (child as { propName: string }).propName as string;
|
|
107
|
+
if (get(values, propName) === undefined) {
|
|
108
|
+
assert(
|
|
109
|
+
`Key "${propName}" not found in ${JSON.stringify(values, null, 2)}`,
|
|
110
|
+
true
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const propValue = values[propName];
|
|
114
|
+
encounteredNonPrimitive =
|
|
115
|
+
encounteredNonPrimitive || !isPrimitive(propValue);
|
|
116
|
+
appendValueToChildren(propValue);
|
|
117
|
+
child = undefined;
|
|
118
|
+
} else {
|
|
119
|
+
appendCharToChild(char);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// include any remaining child value
|
|
124
|
+
appendValueToChildren(child);
|
|
125
|
+
|
|
126
|
+
return encounteredNonPrimitive ? children : children.join('');
|
|
127
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{{#if (arg-or-default @inList true)}}
|
|
2
|
+
<li>
|
|
3
|
+
<EuiPaginationButton
|
|
4
|
+
@isActive={{eq @pageIndex @props.activePage}}
|
|
5
|
+
@totalPages={{@props.pageCount}}
|
|
6
|
+
@pageIndex={{@pageIndex}}
|
|
7
|
+
aria-controls={{@props.ariaControls}}
|
|
8
|
+
@hideOnMobile={{true}}
|
|
9
|
+
{{on "click" (fn @props.safeClick @pageIndex)}}
|
|
10
|
+
/>
|
|
11
|
+
</li>
|
|
12
|
+
{{else}}
|
|
13
|
+
<EuiPaginationButton
|
|
14
|
+
@isActive={{eq @pageIndex @props.activePage}}
|
|
15
|
+
@totalPages={{@props.pageCount}}
|
|
16
|
+
@pageIndex={{@pageIndex}}
|
|
17
|
+
aria-controls={{@props.ariaControls}}
|
|
18
|
+
@hideOnMobile={{true}}
|
|
19
|
+
{{on "click" (fn @props.safeClick @pageIndex)}}
|
|
20
|
+
/>
|
|
21
|
+
{{/if}}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
{{#if @compressed}}
|
|
2
|
+
<nav class="euiPagination" ...attributes>
|
|
3
|
+
<EuiPagination::PreviousButton
|
|
4
|
+
@activePage={{this.activePage}}
|
|
5
|
+
@safeClick={{this.safeClick}}
|
|
6
|
+
@props={{this.prevPageButtonProps}}
|
|
7
|
+
/>
|
|
8
|
+
<EuiHideFor @sizes={{array "xs" "s"}}>
|
|
9
|
+
<EuiText @size="s" class="euiPagination__compressedText">
|
|
10
|
+
<EuiI18n
|
|
11
|
+
@token="euiPagination.pageOfTotalCompressed"
|
|
12
|
+
@default="{page} of {total}"
|
|
13
|
+
@values={{hash
|
|
14
|
+
page=(component
|
|
15
|
+
"eui-pagination/button-wrapper"
|
|
16
|
+
pageIndex=this.activePage
|
|
17
|
+
props=this.sharedButtonProps
|
|
18
|
+
inList=false
|
|
19
|
+
)
|
|
20
|
+
total=(component
|
|
21
|
+
"eui-pagination/button-wrapper"
|
|
22
|
+
pageIndex=(sub this.pageCount 1)
|
|
23
|
+
props=this.sharedButtonProps
|
|
24
|
+
inList=false
|
|
25
|
+
)
|
|
26
|
+
}}
|
|
27
|
+
as |Token|
|
|
28
|
+
>
|
|
29
|
+
<Token as |value|>
|
|
30
|
+
{{value}}
|
|
31
|
+
</Token>
|
|
32
|
+
</EuiI18n>
|
|
33
|
+
</EuiText>
|
|
34
|
+
</EuiHideFor>
|
|
35
|
+
<EuiPagination::NextButton
|
|
36
|
+
@activePage={{this.activePage}}
|
|
37
|
+
@safeClick={{this.safeClick}}
|
|
38
|
+
@props={{this.nextPageButtonProps}}
|
|
39
|
+
/>
|
|
40
|
+
</nav>
|
|
41
|
+
{{else}}
|
|
42
|
+
{{!template-lint-disable no-duplicate-landmark-elements}}
|
|
43
|
+
<nav class="euiPagination" ...attributes>
|
|
44
|
+
<EuiPagination::PreviousButton
|
|
45
|
+
@activePage={{this.activePage}}
|
|
46
|
+
@safeClick={{this.safeClick}}
|
|
47
|
+
@props={{this.prevPageButtonProps}}
|
|
48
|
+
/>
|
|
49
|
+
<ul class="euiPagination__list">
|
|
50
|
+
{{#each this.firstPageButtons as |page|}}
|
|
51
|
+
{{#if page.i18n}}
|
|
52
|
+
<EuiI18n
|
|
53
|
+
@token="euiPagination.firstRangeAriaLabel"
|
|
54
|
+
@default="Skipping pages 2 to {lastPage}"
|
|
55
|
+
@values={{hash lastPage=this.firstPageInRange}}
|
|
56
|
+
as |Token|
|
|
57
|
+
>
|
|
58
|
+
<Token as |firstRangeAriaLabel|>
|
|
59
|
+
<li
|
|
60
|
+
aria-label={{firstRangeAriaLabel}}
|
|
61
|
+
class="euiPaginationButton-isPlaceholder euiPagination__item"
|
|
62
|
+
>
|
|
63
|
+
…
|
|
64
|
+
</li>
|
|
65
|
+
</Token>
|
|
66
|
+
</EuiI18n>
|
|
67
|
+
{{else}}
|
|
68
|
+
<EuiPagination::ButtonWrapper
|
|
69
|
+
@pageIndex={{page.pageIndex}}
|
|
70
|
+
@props={{this.sharedButtonProps}}
|
|
71
|
+
/>
|
|
72
|
+
{{/if}}
|
|
73
|
+
{{/each}}
|
|
74
|
+
{{#each this.pages as |page|}}
|
|
75
|
+
<EuiPagination::ButtonWrapper
|
|
76
|
+
@pageIndex={{page.pageIndex}}
|
|
77
|
+
@props={{this.sharedButtonProps}}
|
|
78
|
+
/>
|
|
79
|
+
{{/each}}
|
|
80
|
+
{{#each this.lastPageButtons as |page|}}
|
|
81
|
+
{{#if page.i18n}}
|
|
82
|
+
<EuiI18n
|
|
83
|
+
@token="euiPagination.lastRangeAriaLabel"
|
|
84
|
+
@default="Skipping pages {firstPage} to {lastPage}"
|
|
85
|
+
@values={{hash
|
|
86
|
+
firstPage=(add this.lastPageInRange 1)
|
|
87
|
+
lastPage=(sub this.pageCount 1)
|
|
88
|
+
}}
|
|
89
|
+
as |Token|
|
|
90
|
+
>
|
|
91
|
+
<Token as |lastRangeAriaLabel|>
|
|
92
|
+
<li
|
|
93
|
+
aria-label={{lastRangeAriaLabel}}
|
|
94
|
+
class="euiPaginationButton-isPlaceholder euiPagination__item"
|
|
95
|
+
>
|
|
96
|
+
…
|
|
97
|
+
</li>
|
|
98
|
+
</Token>
|
|
99
|
+
</EuiI18n>
|
|
100
|
+
{{else}}
|
|
101
|
+
<EuiPagination::ButtonWrapper
|
|
102
|
+
@pageIndex={{page.pageIndex}}
|
|
103
|
+
@props={{this.sharedButtonProps}}
|
|
104
|
+
/>
|
|
105
|
+
{{/if}}
|
|
106
|
+
{{/each}}
|
|
107
|
+
</ul>
|
|
108
|
+
<EuiPagination::NextButton
|
|
109
|
+
@activePage={{this.activePage}}
|
|
110
|
+
@safeClick={{this.safeClick}}
|
|
111
|
+
@props={{this.nextPageButtonProps}}
|
|
112
|
+
/>
|
|
113
|
+
</nav>
|
|
114
|
+
|
|
115
|
+
{{/if}}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
|
|
3
|
+
export type PageClickHandler = (pageIndex: number) => void;
|
|
4
|
+
type SafeClickHandler = (pageIndex: number) => void;
|
|
5
|
+
|
|
6
|
+
interface Args {
|
|
7
|
+
/**
|
|
8
|
+
* The total number of pages.
|
|
9
|
+
*/
|
|
10
|
+
pageCount?: number;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The current page using a zero based index.
|
|
14
|
+
* So if you set the activePage to 1, it will activate the second page.
|
|
15
|
+
*/
|
|
16
|
+
activePage?: number;
|
|
17
|
+
|
|
18
|
+
onPageClick?: PageClickHandler;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* If true, will only show next/prev arrows instead of page numbers.
|
|
22
|
+
*/
|
|
23
|
+
compressed?: boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* If passed in, passes value through to each button to set aria-controls
|
|
27
|
+
*/
|
|
28
|
+
'aria-controls'?: string;
|
|
29
|
+
ariaControls?: string;
|
|
30
|
+
}
|
|
31
|
+
const MAX_VISIBLE_PAGES = 5;
|
|
32
|
+
const NUMBER_SURROUNDING_PAGES = Math.floor(MAX_VISIBLE_PAGES * 0.5);
|
|
33
|
+
|
|
34
|
+
export default class EuiPaginationComponent extends Component<Args> {
|
|
35
|
+
get pageCount() {
|
|
36
|
+
return this.args.pageCount ?? 1;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get activePage() {
|
|
40
|
+
return this.args.activePage ?? 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get ariaControls() {
|
|
44
|
+
return this.args['aria-controls'] || this.args.ariaControls;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get hasControl() {
|
|
48
|
+
return this.ariaControls !== undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get pages() {
|
|
52
|
+
let pages = [];
|
|
53
|
+
const { firstPageInRange, lastPageInRange } = this;
|
|
54
|
+
for (
|
|
55
|
+
let i = firstPageInRange, index = 0;
|
|
56
|
+
i < lastPageInRange;
|
|
57
|
+
i++, index++
|
|
58
|
+
) {
|
|
59
|
+
pages.push({
|
|
60
|
+
pageIndex: i
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return pages;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get firstPageButtons() {
|
|
68
|
+
let firstPageButtons = [];
|
|
69
|
+
if (this.firstPageInRange > 0) {
|
|
70
|
+
firstPageButtons.push({
|
|
71
|
+
pageIndex: 0
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (this.firstPageInRange > 1 && this.firstPageInRange !== 2) {
|
|
75
|
+
firstPageButtons.push({
|
|
76
|
+
i18n: {
|
|
77
|
+
key: 'startingEllipses',
|
|
78
|
+
token: 'euiPagination.firstRangeAriaLabel',
|
|
79
|
+
default: 'Skipping pages 2 to {lastPage}',
|
|
80
|
+
values: { lastPage: this.firstPageInRange }
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
} else if (this.firstPageInRange === 2) {
|
|
84
|
+
firstPageButtons.push({ pageIndex: 1 });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return firstPageButtons;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get lastPageButtons() {
|
|
92
|
+
let lastPageButtons = [];
|
|
93
|
+
let pageCount = this.pageCount;
|
|
94
|
+
let lastPageInRange = this.lastPageInRange;
|
|
95
|
+
|
|
96
|
+
if (lastPageInRange < pageCount) {
|
|
97
|
+
if (lastPageInRange + 1 === pageCount - 1) {
|
|
98
|
+
lastPageButtons.push({ pageIndex: lastPageInRange });
|
|
99
|
+
} else if (lastPageInRange < pageCount - 1) {
|
|
100
|
+
lastPageButtons.push({
|
|
101
|
+
i18n: {
|
|
102
|
+
key: 'endingEllipses',
|
|
103
|
+
token: 'euiPagination.lastRangeAriaLabel',
|
|
104
|
+
default: 'Skipping pages {firstPage} to {lastPage}',
|
|
105
|
+
values: { firstPage: lastPageInRange + 1, lastPage: pageCount - 1 }
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
lastPageButtons.push({ pageIndex: pageCount - 1 });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return lastPageButtons;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get sharedButtonProps() {
|
|
116
|
+
return {
|
|
117
|
+
activePage: this.activePage,
|
|
118
|
+
pageCount: this.pageCount,
|
|
119
|
+
ariaControls: this.ariaControls,
|
|
120
|
+
safeClick: this.safeClick
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
get prevPageButtonProps() {
|
|
125
|
+
let prevPageButtonProps = {};
|
|
126
|
+
if (this.hasControl && this.activePage !== 0) {
|
|
127
|
+
prevPageButtonProps = {
|
|
128
|
+
'aria-controls': this.ariaControls,
|
|
129
|
+
href: `#${this.ariaControls}`
|
|
130
|
+
};
|
|
131
|
+
} else {
|
|
132
|
+
prevPageButtonProps = { disabled: this.activePage === 0 };
|
|
133
|
+
}
|
|
134
|
+
return prevPageButtonProps;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
get nextPageButtonProps() {
|
|
138
|
+
let nextPageButtonProps = {};
|
|
139
|
+
if (this.hasControl && this.activePage !== this.pageCount - 1) {
|
|
140
|
+
nextPageButtonProps = {
|
|
141
|
+
'aria-controls': this.ariaControls,
|
|
142
|
+
href: `#${this.ariaControls}`
|
|
143
|
+
};
|
|
144
|
+
} else {
|
|
145
|
+
nextPageButtonProps = {
|
|
146
|
+
disabled: this.activePage === this.pageCount - 1
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return nextPageButtonProps;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
safeClick: SafeClickHandler = (pageIndex) => {
|
|
153
|
+
if (this.ariaControls) {
|
|
154
|
+
const controlledElement = document.getElementById(this.ariaControls);
|
|
155
|
+
|
|
156
|
+
if (controlledElement) {
|
|
157
|
+
controlledElement.focus();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this.args.onPageClick?.(pageIndex);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
get firstPageInRange() {
|
|
165
|
+
return Math.max(
|
|
166
|
+
0,
|
|
167
|
+
Math.min(
|
|
168
|
+
this.activePage - NUMBER_SURROUNDING_PAGES,
|
|
169
|
+
this.pageCount - MAX_VISIBLE_PAGES
|
|
170
|
+
)
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
get lastPageInRange() {
|
|
175
|
+
return Math.min(this.pageCount, this.firstPageInRange + MAX_VISIBLE_PAGES);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<EuiI18n
|
|
2
|
+
@token="euiPagination.nextPage"
|
|
3
|
+
@default="Next page, {page}"
|
|
4
|
+
@values={{hash page=(add @activePage 2)}}
|
|
5
|
+
as |Token|
|
|
6
|
+
>
|
|
7
|
+
<Token as |nextPage|>
|
|
8
|
+
<EuiI18n
|
|
9
|
+
@token="euiPagination.disabledNextPage"
|
|
10
|
+
@default="Next page"
|
|
11
|
+
as |InnerToken|
|
|
12
|
+
>
|
|
13
|
+
<InnerToken as |disabledNextPage|>
|
|
14
|
+
<EuiButtonIcon
|
|
15
|
+
{{on "click" (fn @safeClick (add @activePage 1))}}
|
|
16
|
+
@iconType="arrowRight"
|
|
17
|
+
@color="text"
|
|
18
|
+
aria-label={{if (eq (sub @activePage -1)) disabledNextPage nextPage}}
|
|
19
|
+
aria-controls={{if @props.aria-controls @props.aria-controls}}
|
|
20
|
+
href={{if @props.href @props.href}}
|
|
21
|
+
disabled={{eq @props.disabled true}}
|
|
22
|
+
...attributes
|
|
23
|
+
/>
|
|
24
|
+
</InnerToken>
|
|
25
|
+
</EuiI18n>
|
|
26
|
+
</Token>
|
|
27
|
+
</EuiI18n>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<EuiI18n
|
|
2
|
+
@token="euiPagination.previousPage"
|
|
3
|
+
@default="Previous page, {page}"
|
|
4
|
+
@values={{hash page=@activePage}}
|
|
5
|
+
as |Token|
|
|
6
|
+
>
|
|
7
|
+
<Token as |previousPage|>
|
|
8
|
+
<EuiI18n
|
|
9
|
+
@token="euiPagination.disabledPreviousPage"
|
|
10
|
+
@default="Previous page"
|
|
11
|
+
as |InnerToken|
|
|
12
|
+
>
|
|
13
|
+
<InnerToken as |disabledPreviousPage|>
|
|
14
|
+
<EuiButtonIcon
|
|
15
|
+
{{on "click" (fn @safeClick (sub @activePage 1))}}
|
|
16
|
+
@iconType="arrowLeft"
|
|
17
|
+
@color="text"
|
|
18
|
+
aria-label={{if (eq @activePage 0) disabledPreviousPage previousPage}}
|
|
19
|
+
aria-controls={{if @props.aria-controls @props.aria-controls}}
|
|
20
|
+
href={{if @props.href @props.href}}
|
|
21
|
+
disabled={{eq @props.disabled true}}
|
|
22
|
+
...attributes
|
|
23
|
+
/>
|
|
24
|
+
</InnerToken>
|
|
25
|
+
</EuiI18n>
|
|
26
|
+
</Token>
|
|
27
|
+
</EuiI18n>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{{#let (add @pageIndex 1) as |pageNumber|}}
|
|
2
|
+
<EuiI18n
|
|
3
|
+
@token="euiPaginationButton.longPageString"
|
|
4
|
+
@default="Page {page} of {totalPages}"
|
|
5
|
+
@values={{hash page=pageNumber totalPages=@totalPages}}
|
|
6
|
+
as |Token|
|
|
7
|
+
>
|
|
8
|
+
<Token as |longPageString|>
|
|
9
|
+
<EuiI18n
|
|
10
|
+
@token="euiPaginationButton.shortPageString"
|
|
11
|
+
@default="Page {page}"
|
|
12
|
+
values={{hash page=pageNumber}}
|
|
13
|
+
as |InnerToken|
|
|
14
|
+
>
|
|
15
|
+
<InnerToken as |shortPageString|>
|
|
16
|
+
<EuiButtonEmpty
|
|
17
|
+
class={{class-names
|
|
18
|
+
"euiPaginationButton"
|
|
19
|
+
(if @isActive "euiPaginationButton-isActive")
|
|
20
|
+
(if @isPlaceholder "euiPaginationButton-isPlaceholder")
|
|
21
|
+
(if @hideOnMobile "euiPaginationButton--hideOnMobile")
|
|
22
|
+
}}
|
|
23
|
+
aria-label={{if @totalPages longPageString shortPageString}}
|
|
24
|
+
@size="s"
|
|
25
|
+
@color="text"
|
|
26
|
+
@isDisabled={{or @isPlaceholder @isActive}}
|
|
27
|
+
aria-current={{if @isActive true}}
|
|
28
|
+
...attributes
|
|
29
|
+
>
|
|
30
|
+
{{pageNumber}}
|
|
31
|
+
</EuiButtonEmpty>
|
|
32
|
+
</InnerToken>
|
|
33
|
+
</EuiI18n>
|
|
34
|
+
</Token>
|
|
35
|
+
</EuiI18n>
|
|
36
|
+
{{/let}}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
5
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
6
|
+
* Side Public License, v 1.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// import moment from 'moment';
|
|
10
|
+
|
|
11
|
+
export const always = (_value?: any) => true;
|
|
12
|
+
|
|
13
|
+
export const never = (_value?: any) => false;
|
|
14
|
+
|
|
15
|
+
export const isUndefined = (value: any): value is undefined => {
|
|
16
|
+
return value === undefined;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const isNull = (value: any): value is null => {
|
|
20
|
+
return value === null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const isNil = (value: any): value is null | undefined => {
|
|
24
|
+
return isUndefined(value) || isNull(value);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// export const isMoment = (value: any) => {
|
|
28
|
+
// return moment.isMoment(value);
|
|
29
|
+
// };
|
|
30
|
+
|
|
31
|
+
// export const isDate = (value: any): value is Date => {
|
|
32
|
+
// return moment.isDate(value);
|
|
33
|
+
// };
|
|
34
|
+
|
|
35
|
+
// export const isDateLike = (value: any): value is moment.Moment | Date => {
|
|
36
|
+
// return isDate(value);
|
|
37
|
+
// };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
5
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
6
|
+
* Side Public License, v 1.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './common_predicates';
|
|
10
|
+
export * from './lodash_predicates';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
5
|
+
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
6
|
+
* Side Public License, v 1.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import _isFunction from 'lodash-es/isFunction';
|
|
10
|
+
import _isArray from 'lodash-es/isArray';
|
|
11
|
+
import _isString from 'lodash-es/isString';
|
|
12
|
+
import _isBoolean from 'lodash-es/isBoolean';
|
|
13
|
+
import _isNumber from 'lodash-es/isNumber';
|
|
14
|
+
import _isNaN from 'lodash-es/isNaN';
|
|
15
|
+
import _isObject from 'lodash-es/isObject';
|
|
16
|
+
|
|
17
|
+
// wrap the lodash functions to avoid having lodash's TS type definition from being
|
|
18
|
+
// exported, which can conflict with the lodash namespace if other versions are used
|
|
19
|
+
|
|
20
|
+
export const isFunction = (value: any): value is (...args: any[]) => any =>
|
|
21
|
+
_isFunction(value);
|
|
22
|
+
export const isArray = (value: any): value is any[] => _isArray(value);
|
|
23
|
+
export const isString = (value: any): value is string => _isString(value);
|
|
24
|
+
export const isBoolean = (value: any): value is boolean => _isBoolean(value);
|
|
25
|
+
export const isNumber = (value: any): value is number => _isNumber(value);
|
|
26
|
+
export const isNaN = (value: any) => _isNaN(value);
|
|
27
|
+
export const isObject = (value: any): value is object => _isObject(value);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@ember-eui/core/components/eui-i18n';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@ember-eui/core/components/eui-i18n/render';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@ember-eui/core/components/eui-pagination/button-wrapper';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@ember-eui/core/components/eui-pagination';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@ember-eui/core/components/eui-pagination/next-button';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@ember-eui/core/components/eui-pagination/previous-button';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@ember-eui/core/components/eui-pagination-button';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@ember-eui/core/i18n';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
order: 1
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Basic usage with many pages
|
|
6
|
+
|
|
7
|
+
<EuiText>
|
|
8
|
+
<p><strong>EuiPagination</strong> accepts a total <EuiCode>pageCount</EuiCode> and only shows up to 5 consecutive pages, with shortcuts to the first and/or last page. It also requires the parent component to maintain the current <EuiCode>activePage</EuiCode> and handle the <EuiCode>onPageClick</EuiCode>.</p>
|
|
9
|
+
</EuiText>
|
|
10
|
+
|
|
11
|
+
```hbs template
|
|
12
|
+
{{#let (use-state 0) as |activePage|}}
|
|
13
|
+
<EuiPagination
|
|
14
|
+
@compressed={{true}}
|
|
15
|
+
@aria-label='Many pages example'
|
|
16
|
+
@pageCount={{22}}
|
|
17
|
+
@activePage={{activePage.value}}
|
|
18
|
+
@onPageClick={{activePage.setState}}
|
|
19
|
+
/>
|
|
20
|
+
<EuiPagination
|
|
21
|
+
@aria-label='Many pages example'
|
|
22
|
+
@pageCount={{22}}
|
|
23
|
+
@activePage={{activePage.value}}
|
|
24
|
+
@onPageClick={{activePage.setState}}
|
|
25
|
+
/>
|
|
26
|
+
{{/let}}
|
|
27
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
order: 1
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<EuiText>
|
|
6
|
+
<p>
|
|
7
|
+
Render strings to components, you can provide a hash containing custom tokens via <EuiCode>{{"@i18n"}}</EuiCode> or override i18n/index.js in your host app to export a hash containg them
|
|
8
|
+
</p>
|
|
9
|
+
</EuiText>
|
|
10
|
+
|
|
11
|
+
```hbs template
|
|
12
|
+
<EuiI18n
|
|
13
|
+
@token='euiPagination.pageOfTotalCompressed'
|
|
14
|
+
@default='{page} of {total}'
|
|
15
|
+
@values={{hash page=(component 'eui-button') total=(component 'eui-button')}}
|
|
16
|
+
as |Token|
|
|
17
|
+
>
|
|
18
|
+
<Token as |value|>
|
|
19
|
+
{{value}}
|
|
20
|
+
</Token>
|
|
21
|
+
</EuiI18n>
|
|
22
|
+
<EuiI18n
|
|
23
|
+
@token='euiPagination.pageOfTotalCompressed'
|
|
24
|
+
@default='{page} other {total}'
|
|
25
|
+
@values={{hash page=10 total=2000}}
|
|
26
|
+
as |Token|
|
|
27
|
+
>
|
|
28
|
+
<Token as |value|>
|
|
29
|
+
{{value}}
|
|
30
|
+
</Token>
|
|
31
|
+
</EuiI18n>
|
|
32
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ember-eui/core",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.8.0",
|
|
4
4
|
"description": "Ember Components for Elastic UI",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon",
|
|
@@ -182,5 +182,5 @@
|
|
|
182
182
|
"volta": {
|
|
183
183
|
"extends": "../../package.json"
|
|
184
184
|
},
|
|
185
|
-
"gitHead": "
|
|
185
|
+
"gitHead": "530ce7498293425660b8904afadcf49b3841303e"
|
|
186
186
|
}
|