-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
0 parents
commit 6f426c7
Showing
204 changed files
with
6,652 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Single Page Apps for GitHub Pages</title> | ||
<script type="text/javascript"> | ||
// Single Page Apps for GitHub Pages | ||
// https://github.com/rafrex/spa-github-pages | ||
// Copyright (c) 2016 Rafael Pedicini, licensed under the MIT License | ||
// ---------------------------------------------------------------------- | ||
// This script takes the current url and converts the path and query | ||
// string into just a query string, and then redirects the browser | ||
// to the new url with only a query string and hash fragment, | ||
// e.g. http://www.foo.tld/one/two?a=b&c=d#qwe, becomes | ||
// http://www.foo.tld/?p=/one/two&q=a=b~and~c=d#qwe | ||
// Note: this 404.html file must be at least 512 bytes for it to work | ||
// with Internet Explorer (it is currently > 512 bytes) | ||
|
||
// If you're creating a Project Pages site and NOT using a custom domain, | ||
// then set segmentCount to 1 (enterprise users may need to set it to > 1). | ||
// This way the code will only replace the route part of the path, and not | ||
// the real directory in which the app resides, for example: | ||
// https://username.github.io/repo-name/one/two?a=b&c=d#qwe becomes | ||
// https://username.github.io/repo-name/?p=/one/two&q=a=b~and~c=d#qwe | ||
// Otherwise, leave segmentCount as 0. | ||
var segmentCount = 1; | ||
|
||
var l = window.location; | ||
l.replace( | ||
l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') + | ||
l.pathname.split('/').slice(0, 1 + segmentCount).join('/') + '/?p=/' + | ||
l.pathname.slice(1).split('/').slice(segmentCount).join('/').replace(/&/g, '~and~') + | ||
(l.search ? '&q=' + l.search.slice(1).replace(/&/g, '~and~') : '') + | ||
l.hash | ||
); | ||
|
||
</script> | ||
</head> | ||
<body> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
@import '_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.bundle.scp.css'; | ||
|
||
/* /Layout/NavMenu.razor.rz.scp.css */ | ||
[b-g6ntd1p53q] .fluent-nav-icon { | ||
padding-top: 5px; | ||
} |
10 changes: 10 additions & 0 deletions
10
_content/Microsoft.FluentUI.AspNetCore.Components/Components/Anchor/FluentAnchor.razor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export function scrollIntoView(elementId) { | ||
// This function is called from the AnchorLink component using JavaScript interop. | ||
// It will try to find an element using the ID given to the function, and scroll that | ||
// element into view, if an element is found. | ||
var elem = document.getElementById(elementId); | ||
if (elem) { | ||
elem.scrollIntoView(); | ||
window.location.hash = elementId; | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
...ft.FluentUI.AspNetCore.Components/Components/AnchoredRegion/FluentAnchoredRegion.razor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
export function goToNextFocusableElement(forContainer, toOriginal, delay) { | ||
|
||
const container = typeof forContainer === "string" ? document.getElementById(forContainer) : forContainer; | ||
|
||
if (!!!container.focusableElement) { | ||
container.focusableElement = new FocusableElement(container); | ||
} | ||
|
||
// Move the focus to the inital element | ||
if (toOriginal === true) { | ||
container.focusableElement.originalActiveElement.focus(); | ||
} | ||
|
||
// Move to the next element | ||
else { | ||
// Find the next focusable element | ||
const nextElement = container.focusableElement.findNextFocusableElement(); | ||
|
||
// Set focus on the next element, | ||
// after delay to give FluentUI web components time to build up | ||
if (nextElement) { | ||
if (delay > 0) { | ||
container.focusableElement.setFocusAfterDelay(nextElement, delay); | ||
} | ||
else { | ||
nextElement.focus(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Focusable Element | ||
*/ | ||
class FocusableElement { | ||
|
||
FOCUSABLE_SELECTORS = "input, select, textarea, button, object, a[href], area[href], [tabindex]"; | ||
_originalActiveElement; | ||
_container; | ||
|
||
/** | ||
* Initializes a new instance of the FocusableElement class. | ||
*/ | ||
constructor(container) { | ||
this._originalActiveElement = document.activeElement; | ||
this._container = container; | ||
} | ||
|
||
/** | ||
* Gets the original document.activeElement before the focus was set to the current element. | ||
*/ | ||
get originalActiveElement() { | ||
return this._originalActiveElement; | ||
} | ||
|
||
/** | ||
* Find the next focusable element, after the optional current element, in the specified container. | ||
* @param container | ||
* @param currentElement | ||
* @returns | ||
*/ | ||
findNextFocusableElement(currentElement) { | ||
// Get all focusable elements | ||
const focusableElements = this._container.querySelectorAll(this.FOCUSABLE_SELECTORS); | ||
|
||
// Filter out elements with tabindex="-1" | ||
const filteredElements = Array.from(focusableElements).filter(el => el?.tabIndex !== -1); | ||
|
||
// Find the index of the current element | ||
const current = currentElement ?? document.activeElement; | ||
if (current != null) { | ||
const currentIndex = filteredElements.indexOf(current); | ||
|
||
// Calculate the index of the next element | ||
const nextIndex = (currentIndex + 1) % filteredElements.length; | ||
|
||
// Return the next focusable element | ||
return filteredElements[nextIndex]; | ||
} | ||
|
||
// Not found | ||
return null; | ||
} | ||
|
||
/** | ||
* Set focus on the specified element after a delay. | ||
* @param element | ||
* @param delayInMilliseconds | ||
*/ | ||
setFocusAfterDelay(element, delayInMilliseconds) { | ||
setTimeout(() => { | ||
const elt = typeof element === "string" ? document.getElementById(element) : element; | ||
if (elt) { | ||
elt.focus(); | ||
} | ||
}, delayInMilliseconds); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
_content/Microsoft.FluentUI.AspNetCore.Components/Components/Button/FluentButton.razor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// workaround for https://github.com/microsoft/fast/issues/5675 | ||
export function updateProxy(id) { | ||
if (!id) { | ||
return; | ||
} | ||
const element = document.getElementById(id); | ||
|
||
if (element && element.form) { | ||
if (element.form.id !== '') { | ||
element.proxy.setAttribute("form", element.form.id) | ||
} | ||
else { | ||
console.warn("When the submit button is placed outside of the EditForm, make sure to supply an id attribute to the EditForm."); | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...tent/Microsoft.FluentUI.AspNetCore.Components/Components/Checkbox/FluentCheckbox.razor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export function setFluentCheckBoxIndeterminate(id, indeterminate, checked) { | ||
var item = document.getElementById(id); | ||
if (!!item) { | ||
item.isUpdating = true; | ||
|
||
// Need to update Checked before Indeterminate | ||
item.checked = checked; | ||
item.indeterminate = indeterminate; | ||
|
||
item.isUpdating = false; | ||
} | ||
} |
203 changes: 203 additions & 0 deletions
203
...tent/Microsoft.FluentUI.AspNetCore.Components/Components/DataGrid/FluentDataGrid.razor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
let initialColumnsWidths = ''; | ||
export function init(gridElement) { | ||
if (gridElement === undefined || gridElement === null) { | ||
return; | ||
}; | ||
|
||
if (gridElement.querySelectorAll('.column-header.resizable').length > 0) { | ||
initialColumnsWidths = gridElement.gridTemplateColumns; | ||
enableColumnResizing(gridElement); | ||
} | ||
|
||
const bodyClickHandler = event => { | ||
const columnOptionsElement = gridElement?.querySelector('.col-options'); | ||
if (columnOptionsElement && event.composedPath().indexOf(columnOptionsElement) < 0) { | ||
gridElement.dispatchEvent(new CustomEvent('closecolumnoptions', { bubbles: true })); | ||
} | ||
}; | ||
const keyDownHandler = event => { | ||
const columnOptionsElement = gridElement?.querySelector('.col-options'); | ||
if (columnOptionsElement) { | ||
if (event.key === "Escape") { | ||
gridElement.dispatchEvent(new CustomEvent('closecolumnoptions', { bubbles: true })); | ||
gridElement.focus(); | ||
} | ||
columnOptionsElement.addEventListener( | ||
"keydown", | ||
(event) => { | ||
if (event.key === "ArrowRight" || event.key === "ArrowLeft" || event.key === "ArrowDown" || event.key === "ArrowUp") { | ||
event.stopPropagation(); | ||
} | ||
} | ||
); | ||
} | ||
}; | ||
|
||
const cells = gridElement.querySelectorAll('[role="gridcell"]'); | ||
cells.forEach((cell) => { | ||
cell.columnDefinition = { | ||
columnDataKey: "", | ||
cellInternalFocusQueue: true, | ||
cellFocusTargetCallback: (cell) => { | ||
return cell.children[0]; | ||
} | ||
} | ||
cell.addEventListener( | ||
"keydown", | ||
(event) => { | ||
if (event.target.role !== "gridcell" && (event.key === "ArrowRight" || event.key === "ArrowLeft")) { | ||
event.stopPropagation(); | ||
} | ||
} | ||
); | ||
}); | ||
|
||
document.body.addEventListener('click', bodyClickHandler); | ||
document.body.addEventListener('mousedown', bodyClickHandler); // Otherwise it seems strange that it doesn't go away until you release the mouse button | ||
document.body.addEventListener('keydown', keyDownHandler); | ||
|
||
return { | ||
stop: () => { | ||
document.body.removeEventListener('click', bodyClickHandler); | ||
document.body.removeEventListener('mousedown', bodyClickHandler); | ||
document.body.removeEventListener('keydown', keyDownHandler); | ||
} | ||
}; | ||
} | ||
|
||
export function checkColumnOptionsPosition(gridElement) { | ||
const colOptions = gridElement?._rowItems[0] && gridElement?.querySelector('.col-options'); // Only match within *our* thead, not nested tables | ||
if (colOptions) { | ||
// We want the options popup to be positioned over the grid, not overflowing on either side, because it's possible that | ||
// beyond either side is off-screen or outside the scroll range of an ancestor | ||
const gridRect = gridElement.getBoundingClientRect(); | ||
const optionsRect = colOptions.getBoundingClientRect(); | ||
const leftOverhang = Math.max(0, gridRect.left - optionsRect.left); | ||
const rightOverhang = Math.max(0, optionsRect.right - gridRect.right); | ||
if (leftOverhang || rightOverhang) { | ||
// In the unlikely event that it overhangs both sides, we'll center it | ||
const applyOffset = leftOverhang && rightOverhang ? (leftOverhang - rightOverhang) / 2 : (leftOverhang - rightOverhang); | ||
colOptions.style.transform = `translateX(${applyOffset}px)`; | ||
} | ||
|
||
colOptions.scrollIntoViewIfNeeded(); | ||
|
||
const autoFocusElem = colOptions.querySelector('[autofocus]'); | ||
if (autoFocusElem) { | ||
autoFocusElem.focus(); | ||
} | ||
} | ||
} | ||
|
||
export function enableColumnResizing(gridElement) { | ||
const columns = []; | ||
let min = 50; | ||
let headerBeingResized; | ||
let resizeHandle; | ||
|
||
gridElement.querySelectorAll('.column-header.resizable').forEach(header => { | ||
columns.push({ header }); | ||
const onPointerMove = (e) => requestAnimationFrame(() => { | ||
if (!headerBeingResized) { | ||
return; | ||
} | ||
|
||
const gridLeft = gridElement.getBoundingClientRect().left; | ||
const headerLocalLeft = headerBeingResized.getBoundingClientRect().left - gridLeft; | ||
const pointerLocalLeft = e.clientX - gridLeft; | ||
|
||
const width = pointerLocalLeft - headerLocalLeft; | ||
|
||
const column = columns.find(({ header }) => header === headerBeingResized); | ||
min = header.querySelector('.col-options-button') ? 75 : 50; | ||
|
||
column.size = Math.max(min, width) + 'px'; | ||
|
||
// Set initial sizes | ||
columns.forEach((column) => { | ||
if (column.size === undefined) { | ||
if (column.header.clientWidth === undefined || column.header.clientWidth === 0) { | ||
column.size = '50px'; | ||
} else { | ||
column.size = column.header.clientWidth + 'px'; | ||
} | ||
} | ||
}); | ||
|
||
gridElement.gridTemplateColumns = columns | ||
.map(({ size }) => size) | ||
.join(' '); | ||
}); | ||
|
||
const onPointerUp = () => { | ||
headerBeingResized = undefined; | ||
resizeHandle = undefined; | ||
}; | ||
|
||
const initResize = ({ target, pointerId }) => { | ||
resizeHandle = target; | ||
headerBeingResized = target.parentNode; | ||
|
||
resizeHandle.setPointerCapture(pointerId); | ||
}; | ||
|
||
const dragHandle = header.querySelector('.col-width-draghandle'); | ||
if (dragHandle) { | ||
dragHandle.addEventListener('pointerdown', initResize); | ||
dragHandle.addEventListener('pointermove', onPointerMove); | ||
dragHandle.addEventListener('pointerup', onPointerUp); | ||
dragHandle.addEventListener('pointercancel', onPointerUp); | ||
dragHandle.addEventListener('pointerleave', onPointerUp); | ||
} | ||
}); | ||
} | ||
|
||
export function resetColumnWidths(gridElement) { | ||
|
||
gridElement.gridTemplateColumns = initialColumnsWidths; | ||
} | ||
|
||
export function resizeColumn(gridElement, change) { | ||
|
||
let headers = gridElement.querySelectorAll('.column-header.resizable'); | ||
if (headers.length <= 0) { | ||
return | ||
} | ||
|
||
if (!(document.activeElement.classList.contains("column-header") && document.activeElement.classList.contains("resizable"))) { | ||
return; | ||
} | ||
const columns = []; | ||
let headerBeingResized = document.activeElement; | ||
let min = 50; | ||
|
||
headers.forEach(header => { | ||
if (header === headerBeingResized) { | ||
min = headerBeingResized.querySelector('.col-options-button') ? 75 : 50; | ||
|
||
const width = headerBeingResized.getBoundingClientRect().width + change; | ||
|
||
if (change < 0) { | ||
header.size = Math.max(min, width) + 'px'; | ||
} | ||
else { | ||
header.size = width + 'px'; | ||
} | ||
} | ||
else { | ||
if (header.size === undefined) { | ||
if (header.clientWidth === undefined || header.clientWidth === 0) { | ||
header.size = min + 'px'; | ||
} else { | ||
header.size = header.clientWidth + 'px'; | ||
} | ||
} | ||
} | ||
|
||
columns.push({ header }); | ||
}); | ||
|
||
gridElement.gridTemplateColumns = columns | ||
.map(({ header }) => header.size) | ||
.join(' '); | ||
} |
Oops, something went wrong.