Repository: grommet/grommet (JavaScript)

Issue:
DataTable still sorts the data even if external of sort props is set. 
### Expected Behavior
If I provide a sort prop like `sort={property: "a", direction: "asc", external: true}`, the data should NOT be sorted when the header is clicked. Instead, I should be able to handle the sort in `onSort`. 

### Actual Behavior
The data still sorts itself. 

<!--- Tell us what happens instead -->

### URL, screen shot, or Codepen exhibiting the issue

Here is a link with a most basic example.
https://codesandbox.io/s/grommet-v2-template-forked-ly6rc?fontsize=14&hidenavigation=1&theme=dark

### Steps to Reproduce

Click the header and the data will still be sorted. 

### Your Environment
- Grommet version: 2.15.2

### Potential Bug Location
Under DataTable.js, in the `onSort` function, it seems that `nextSort` does not take `external` into account.

```
const onSort = property => () => {
let direction;
    if (!sort || property !== sort.property) direction = 'asc';
    else if (sort.direction === 'asc') direction = 'desc';
    else direction = 'asc';
    const nextSort = { property, direction };
    setSort(nextSort);
    if (onSortProp) onSortProp(nextSort);
  };
```



Discussion:

Patch:
diff --git a/src/js/components/DataTable/DataTable.js b/src/js/components/DataTable/DataTable.js
index 477d7cc6d73..46c26085710 100644
--- a/src/js/components/DataTable/DataTable.js
+++ b/src/js/components/DataTable/DataTable.js
@@ -129,11 +129,12 @@ const DataTable = ({
 
   // toggle the sort direction on this property
   const onSort = property => () => {
+    const external = sort ? sort.external : false;
     let direction;
     if (!sort || property !== sort.property) direction = 'asc';
     else if (sort.direction === 'asc') direction = 'desc';
     else direction = 'asc';
-    const nextSort = { property, direction };
+    const nextSort = { property, direction, external };
     setSort(nextSort);
     if (onSortProp) onSortProp(nextSort);
   };


Test patch:
diff --git a/src/js/components/DataTable/__tests__/DataTable-test.js b/src/js/components/DataTable/__tests__/DataTable-test.js
index bbf43623eb1..f6698ca87e3 100644
--- a/src/js/components/DataTable/__tests__/DataTable-test.js
+++ b/src/js/components/DataTable/__tests__/DataTable-test.js
@@ -162,6 +162,39 @@ describe('DataTable', () => {
     expect(container.firstChild).toMatchSnapshot();
   });
 
+  test('onSort external', () => {
+    const onSort = jest.fn();
+    const { container, getByText } = render(
+      <Grommet>
+        <DataTable
+          columns={[
+            { property: 'a', header: 'A' },
+            { property: 'b', header: 'B' },
+          ]}
+          data={[
+            { a: 'zero', b: 0 },
+            { a: 'one', b: 1 },
+            { a: 'two', b: 2 },
+          ]}
+          onSort={onSort}
+          sort={{ property: 'a', direction: 'asc', external: true }}
+        />
+      </Grommet>,
+    );
+    expect(container.firstChild).toMatchSnapshot();
+
+    const headerCell = getByText('A');
+    fireEvent.click(headerCell, {});
+    expect(onSort).toBeCalledWith(
+      expect.objectContaining({
+        property: 'a',
+        direction: 'desc',
+        external: true,
+      }),
+    );
+    expect(container.firstChild).toMatchSnapshot();
+  });
+
   test('sort', () => {
     const { container } = render(
       <Grommet>
diff --git a/src/js/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap b/src/js/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap
index a6fafb752f5..9577a9cb4fe 100644
--- a/src/js/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap
+++ b/src/js/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap
@@ -6572,6 +6572,609 @@ exports[`DataTable onSort 2`] = `
 </div>
 `;
 
+exports[`DataTable onSort external 1`] = `
+.c9 {
+  display: inline-block;
+  -webkit-flex: 0 0 auto;
+  -ms-flex: 0 0 auto;
+  flex: 0 0 auto;
+  width: 24px;
+  height: 24px;
+  fill: #666666;
+  stroke: #666666;
+}
+
+.c9 g {
+  fill: inherit;
+  stroke: inherit;
+}
+
+.c9 *:not([stroke])[fill="none"] {
+  stroke-width: 0;
+}
+
+.c9 *[stroke*="#"],
+.c9 *[STROKE*="#"] {
+  stroke: inherit;
+  fill: none;
+}
+
+.c9 *[fill-rule],
+.c9 *[FILL-RULE],
+.c9 *[fill*="#"],
+.c9 *[FILL*="#"] {
+  fill: inherit;
+  stroke: none;
+}
+
+.c0 {
+  font-size: 18px;
+  line-height: 24px;
+  box-sizing: border-box;
+  -webkit-text-size-adjust: 100%;
+  -ms-text-size-adjust: 100%;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-font-smoothing: antialiased;
+}
+
+.c4 {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  box-sizing: border-box;
+  max-width: 100%;
+  min-width: 0;
+  min-height: 0;
+  -webkit-flex-direction: column;
+  -ms-flex-direction: column;
+  flex-direction: column;
+  -webkit-flex: 1 0 auto;
+  -ms-flex: 1 0 auto;
+  flex: 1 0 auto;
+}
+
+.c6 {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  box-sizing: border-box;
+  max-width: 100%;
+  -webkit-align-items: center;
+  -webkit-box-align: center;
+  -ms-flex-align: center;
+  align-items: center;
+  min-width: 0;
+  min-height: 0;
+  -webkit-flex-direction: row;
+  -ms-flex-direction: row;
+  flex-direction: row;
+}
+
+.c12 {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  box-sizing: border-box;
+  max-width: 100%;
+  min-width: 0;
+  min-height: 0;
+  -webkit-flex-direction: column;
+  -ms-flex-direction: column;
+  flex-direction: column;
+}
+
+.c8 {
+  -webkit-flex: 0 0 auto;
+  -ms-flex: 0 0 auto;
+  flex: 0 0 auto;
+  -webkit-align-self: stretch;
+  -ms-flex-item-align: stretch;
+  align-self: stretch;
+  width: 6px;
+}
+
+.c5 {
+  display: inline-block;
+  box-sizing: border-box;
+  cursor: pointer;
+  font: inherit;
+  -webkit-text-decoration: none;
+  text-decoration: none;
+  margin: 0;
+  background: transparent;
+  overflow: visible;
+  text-transform: none;
+  color: inherit;
+  outline: none;
+  border: none;
+  padding: 0;
+  text-align: inherit;
+  height: 100%;
+}
+
+.c5:focus {
+  outline: none;
+  box-shadow: 0 0 2px 2px #6FFFB0;
+}
+
+.c5:focus > circle,
+.c5:focus > ellipse,
+.c5:focus > line,
+.c5:focus > path,
+.c5:focus > polygon,
+.c5:focus > polyline,
+.c5:focus > rect {
+  outline: none;
+  box-shadow: 0 0 2px 2px #6FFFB0;
+}
+
+.c5:focus::-moz-focus-inner {
+  border: 0;
+}
+
+.c3 {
+  margin: 0;
+  padding: 0;
+  font-weight: inherit;
+  text-align: inherit;
+  text-align: start;
+  border-bottom: solid 1px rgba(0,0,0,0.33);
+  padding-left: 12px;
+  padding-right: 12px;
+  padding-top: 6px;
+  padding-bottom: 6px;
+}
+
+.c11 {
+  margin: 0;
+  padding: 0;
+  font-weight: inherit;
+  text-align: inherit;
+  text-align: start;
+  padding-left: 12px;
+  padding-right: 12px;
+  padding-top: 6px;
+  padding-bottom: 6px;
+}
+
+.c1 {
+  border-spacing: 0;
+  border-collapse: collapse;
+  width: inherit;
+}
+
+.c7 {
+  font-size: 18px;
+  line-height: 24px;
+}
+
+.c13 {
+  font-size: 18px;
+  line-height: 24px;
+  font-weight: bold;
+}
+
+.c2 {
+  border-spacing: 0;
+  border-collapse: separate;
+  height: auto;
+}
+
+.c10:focus {
+  outline: 2px solid #6FFFB0;
+}
+
+@media only screen and (max-width:768px) {
+  .c8 {
+    width: 3px;
+  }
+}
+
+@media all and (min--moz-device-pixel-ratio:0) {
+  .c1 {
+    table-layout: fixed;
+  }
+}
+
+<div
+  class="c0"
+>
+  <table
+    class="c1 c2"
+  >
+    <thead
+      class="StyledTable__StyledTableHeader-sc-1m3u5g-4 StyledDataTable__StyledDataTableHeader-xrlyjm-3"
+    >
+      <tr
+        class="StyledTable__StyledTableRow-sc-1m3u5g-2 "
+      >
+        <th
+          class="c3 "
+          scope="col"
+        >
+          <div
+            class="c4"
+          >
+            <button
+              class="c5 Header__StyledHeaderCellButton-sc-1baku5q-0"
+              type="button"
+            >
+              <div
+                class="c6"
+              >
+                <span
+                  class="c7"
+                >
+                  A
+                </span>
+                <div
+                  class="c8"
+                />
+                <svg
+                  aria-label="FormUp"
+                  class="c9"
+                  viewBox="0 0 24 24"
+                >
+                  <polyline
+                    fill="none"
+                    points="18 9 12 15 6 9"
+                    stroke="#000"
+                    stroke-width="2"
+                    transform="matrix(1 0 0 -1 0 24)"
+                  />
+                </svg>
+              </div>
+            </button>
+          </div>
+        </th>
+        <th
+          class="c3 "
+          scope="col"
+        >
+          <div
+            class="c4"
+          >
+            <button
+              class="c5 Header__StyledHeaderCellButton-sc-1baku5q-0"
+              type="button"
+            >
+              <div
+                class="c6"
+              >
+                <span
+                  class="c7"
+                >
+                  B
+                </span>
+              </div>
+            </button>
+          </div>
+        </th>
+      </tr>
+    </thead>
+    <tbody
+      class="StyledTable__StyledTableBody-sc-1m3u5g-3 c10"
+    >
+      <tr
+        class="StyledTable__StyledTableRow-sc-1m3u5g-2 "
+      >
+        <th
+          class="c11 "
+          scope="row"
+        >
+          <div
+            class="c12"
+          >
+            <span
+              class="c13"
+            >
+              zero
+            </span>
+          </div>
+        </th>
+        <td
+          class="c11 "
+        >
+          <div
+            class="c12"
+          >
+            <span
+              class="c7"
+            >
+              0
+            </span>
+          </div>
+        </td>
+      </tr>
+      <tr
+        class="StyledTable__StyledTableRow-sc-1m3u5g-2 "
+      >
+        <th
+          class="c11 "
+          scope="row"
+        >
+          <div
+            class="c12"
+          >
+            <span
+              class="c13"
+            >
+              one
+            </span>
+          </div>
+        </th>
+        <td
+          class="c11 "
+        >
+          <div
+            class="c12"
+          >
+            <span
+              class="c7"
+            >
+              1
+            </span>
+          </div>
+        </td>
+      </tr>
+      <tr
+        class="StyledTable__StyledTableRow-sc-1m3u5g-2 "
+      >
+        <th
+          class="c11 "
+          scope="row"
+        >
+          <div
+            class="c12"
+          >
+            <span
+              class="c13"
+            >
+              two
+            </span>
+          </div>
+        </th>
+        <td
+          class="c11 "
+        >
+          <div
+            class="c12"
+          >
+            <span
+              class="c7"
+            >
+              2
+            </span>
+          </div>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+</div>
+`;
+
+exports[`DataTable onSort external 2`] = `
+<div
+  class="StyledGrommet-sc-19lkkz7-0 djOnwZ"
+>
+  <table
+    class="StyledTable-sc-1m3u5g-6 kzMUEM StyledDataTable-xrlyjm-0 maGPF"
+  >
+    <thead
+      class="StyledTable__StyledTableHeader-sc-1m3u5g-4 StyledDataTable__StyledDataTableHeader-xrlyjm-3"
+    >
+      <tr
+        class="StyledTable__StyledTableRow-sc-1m3u5g-2 StyledDataTable__StyledDataTableRow-xrlyjm-1 kHghvN"
+      >
+        <th
+          class="StyledTable__StyledTableCell-sc-1m3u5g-0 gAxdWq StyledDataTable__StyledDataTableCell-xrlyjm-5 dBOPzS"
+          scope="col"
+        >
+          <div
+            class="StyledBox-sc-13pk1d4-0 dTCmQX"
+          >
+            <button
+              class="StyledButton-sc-323bzc-0 gtpnsM Header__StyledHeaderCellButton-sc-1baku5q-0"
+              type="button"
+            >
+              <div
+                class="StyledBox-sc-13pk1d4-0 dfYOnT"
+              >
+                <span
+                  class="StyledText-sc-1sadyjn-0 DkZvS"
+                >
+                  A
+                </span>
+                <div
+                  class="StyledBox__StyledBoxGap-sc-13pk1d4-1 bAwsPu"
+                />
+                .c0 {
+  display: inline-block;
+  -webkit-flex: 0 0 auto;
+  -ms-flex: 0 0 auto;
+  flex: 0 0 auto;
+  width: 24px;
+  height: 24px;
+  fill: #666666;
+  stroke: #666666;
+}
+
+.c0 g {
+  fill: inherit;
+  stroke: inherit;
+}
+
+.c0 *:not([stroke])[fill="none"] {
+  stroke-width: 0;
+}
+
+.c0 *[stroke*="#"],
+.c0 *[STROKE*="#"] {
+  stroke: inherit;
+  fill: none;
+}
+
+.c0 *[fill-rule],
+.c0 *[FILL-RULE],
+.c0 *[fill*="#"],
+.c0 *[FILL*="#"] {
+  fill: inherit;
+  stroke: none;
+}
+
+@media only screen and (max-width:768px) {
+
+}
+
+@media all and (min--moz-device-pixel-ratio:0) {
+
+}
+
+<svg
+                  aria-label="FormDown"
+                  class="c0"
+                  viewBox="0 0 24 24"
+                >
+                  <polyline
+                    fill="none"
+                    points="18 9 12 15 6 9"
+                    stroke="#000"
+                    stroke-width="2"
+                  />
+                </svg>
+              </div>
+            </button>
+          </div>
+        </th>
+        <th
+          class="StyledTable__StyledTableCell-sc-1m3u5g-0 gAxdWq StyledDataTable__StyledDataTableCell-xrlyjm-5 dBOPzS"
+          scope="col"
+        >
+          <div
+            class="StyledBox-sc-13pk1d4-0 dTCmQX"
+          >
+            <button
+              class="StyledButton-sc-323bzc-0 gtpnsM Header__StyledHeaderCellButton-sc-1baku5q-0"
+              type="button"
+            >
+              <div
+                class="StyledBox-sc-13pk1d4-0 dfYOnT"
+              >
+                <span
+                  class="StyledText-sc-1sadyjn-0 DkZvS"
+                >
+                  B
+                </span>
+              </div>
+            </button>
+          </div>
+        </th>
+      </tr>
+    </thead>
+    <tbody
+      class="StyledTable__StyledTableBody-sc-1m3u5g-3 StyledDataTable__StyledDataTableBody-xrlyjm-2 gKyMTl"
+    >
+      <tr
+        class="StyledTable__StyledTableRow-sc-1m3u5g-2 StyledDataTable__StyledDataTableRow-xrlyjm-1 kHghvN"
+      >
+        <th
+          class="StyledTable__StyledTableCell-sc-1m3u5g-0 btpZjA StyledDataTable__StyledDataTableCell-xrlyjm-5 dBOPzS"
+          scope="row"
+        >
+          <div
+            class="StyledBox-sc-13pk1d4-0 dYebPD"
+          >
+            <span
+              class="StyledText-sc-1sadyjn-0 JhXAc"
+            >
+              zero
+            </span>
+          </div>
+        </th>
+        <td
+          class="StyledTable__StyledTableCell-sc-1m3u5g-0 btpZjA StyledDataTable__StyledDataTableCell-xrlyjm-5 dBOPzS"
+        >
+          <div
+            class="StyledBox-sc-13pk1d4-0 dYebPD"
+          >
+            <span
+              class="StyledText-sc-1sadyjn-0 DkZvS"
+            >
+              0
+            </span>
+          </div>
+        </td>
+      </tr>
+      <tr
+        class="StyledTable__StyledTableRow-sc-1m3u5g-2 StyledDataTable__StyledDataTableRow-xrlyjm-1 kHghvN"
+      >
+        <th
+          class="StyledTable__StyledTableCell-sc-1m3u5g-0 btpZjA StyledDataTable__StyledDataTableCell-xrlyjm-5 dBOPzS"
+          scope="row"
+        >
+          <div
+            class="StyledBox-sc-13pk1d4-0 dYebPD"
+          >
+            <span
+              class="StyledText-sc-1sadyjn-0 JhXAc"
+            >
+              one
+            </span>
+          </div>
+        </th>
+        <td
+          class="StyledTable__StyledTableCell-sc-1m3u5g-0 btpZjA StyledDataTable__StyledDataTableCell-xrlyjm-5 dBOPzS"
+        >
+          <div
+            class="StyledBox-sc-13pk1d4-0 dYebPD"
+          >
+            <span
+              class="StyledText-sc-1sadyjn-0 DkZvS"
+            >
+              1
+            </span>
+          </div>
+        </td>
+      </tr>
+      <tr
+        class="StyledTable__StyledTableRow-sc-1m3u5g-2 StyledDataTable__StyledDataTableRow-xrlyjm-1 kHghvN"
+      >
+        <th
+          class="StyledTable__StyledTableCell-sc-1m3u5g-0 btpZjA StyledDataTable__StyledDataTableCell-xrlyjm-5 dBOPzS"
+          scope="row"
+        >
+          <div
+            class="StyledBox-sc-13pk1d4-0 dYebPD"
+          >
+            <span
+              class="StyledText-sc-1sadyjn-0 JhXAc"
+            >
+              two
+            </span>
+          </div>
+        </th>
+        <td
+          class="StyledTable__StyledTableCell-sc-1m3u5g-0 btpZjA StyledDataTable__StyledDataTableCell-xrlyjm-5 dBOPzS"
+        >
+          <div
+            class="StyledBox-sc-13pk1d4-0 dYebPD"
+          >
+            <span
+              class="StyledText-sc-1sadyjn-0 DkZvS"
+            >
+              2
+            </span>
+          </div>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+</div>
+`;
+
 exports[`DataTable pad 1`] = `
 .c0 {
   font-size: 18px;